import React, { useRef, useState, useEffect } from 'react';
import { INSTRUMENTS, BASS_NOTES, MIN_TEMPO, MAX_TEMPO, MIN_STEPS, MAX_STEPS } from '../constants';
import { PlayIcon, StopIcon, ClearIcon, UploadIcon, DownloadIcon, PlusIcon, MinusIcon } from './icons';
import { Grid, BassLineGrid } from '../types';
import { Modal } from './Modal';

interface SequencerProps {
    steps: number;
    grid: Grid;
    bassLine: BassLineGrid;
    isPlaying: boolean;
    tempo: number;
    currentStep: number | null;
    mutes: boolean[];
    drumVolume: number;
    bassVolume: number;
    setStep: (instrumentIndex: number, stepIndex: number, isActive: boolean) => void;
    setBassNote: (stepIndex: number, note: string) => void;
    clearPattern: () => void;
    setTempo: React.Dispatch<React.SetStateAction<number>>;
    handleStepsChange: (newSteps: number) => void;
    startPlayback: () => Promise<void>;
    stopPlayback: () => void;
    exportBeat: () => void;
    importBeat: (event: React.ChangeEvent<HTMLInputElement>) => void;
    toggleMute: (instrumentIndex: number) => void;
    handleDrumVolumeChange: (newVolume: number) => void;
    handleBassVolumeChange: (newVolume: number) => void;
    triggerSound: (instrumentName: string) => void;
    triggerBassNote: (note: string) => void;
}

const ControlButton: React.FC<{ onClick?: () => void; children: React.ReactNode; className?: string; disabled?: boolean; title?: string }> = ({ onClick, children, className, disabled, title }) => (
    <button
        onClick={onClick}
        disabled={disabled}
        title={title}
        className={`flex items-center justify-center gap-2 px-3 py-1.5 text-[11px] font-black uppercase tracking-widest text-slate-600 bg-white border border-slate-200 rounded shadow-sm hover:bg-slate-50 hover:border-slate-300 transition-all active:scale-95 disabled:opacity-40 disabled:cursor-not-allowed ${className}`}
    >
        {children}
    </button>
);

const IconButton: React.FC<{ onClick?: () => void; children: React.ReactNode; className?: string; disabled?: boolean }> = ({ onClick, children, className, disabled }) => (
    <button
        onClick={onClick}
        disabled={disabled}
        className={`p-1.5 text-slate-400 hover:text-slate-600 hover:bg-slate-100 rounded transition-colors disabled:opacity-30 ${className}`}
    >
        {children}
    </button>
);

export const Sequencer: React.FC<SequencerProps> = ({
    steps, grid, isPlaying, tempo, currentStep, mutes, bassLine,
    drumVolume, bassVolume,
    clearPattern, setTempo, handleStepsChange, setStep, setBassNote,
    startPlayback, stopPlayback, exportBeat, importBeat,
    handleDrumVolumeChange, handleBassVolumeChange, triggerSound, triggerBassNote
}) => {

    const fileInputRef = useRef<HTMLInputElement>(null);
    const [isDragging, setIsDragging] = useState(false);
    const [dragActivationState, setDragActivationState] = useState(false);
    const [dragStartRow, setDragStartRow] = useState<number | null>(null);

    const [isBassDragging, setIsBassDragging] = useState(false);
    const [bassDragActivationState, setBassDragActivationState] = useState(false);
    const [isClearModalOpen, setIsClearModalOpen] = useState(false);

    useEffect(() => {
        const handleMouseUp = () => {
            setIsDragging(false);
            setDragStartRow(null);
            setIsBassDragging(false);
        };
        window.addEventListener('mouseup', handleMouseUp);
        return () => window.removeEventListener('mouseup', handleMouseUp);
    }, []);

    const handleCellMouseDown = (instIndex: number, stepIndex: number) => {
        setIsDragging(true);
        setDragStartRow(instIndex);
        const newState = !grid[instIndex]?.[stepIndex];
        setDragActivationState(newState);
        setStep(instIndex, stepIndex, newState);
        if (newState && !isPlaying) {
            triggerSound(INSTRUMENTS[instIndex].name);
        }
    };

    const handleCellMouseEnter = (instIndex: number, stepIndex: number) => {
        if (isDragging && instIndex === dragStartRow) {
            setStep(instIndex, stepIndex, dragActivationState);
        }
    };

    const handleBassCellMouseDown = (noteName: string, stepIndex: number) => {
        const isCurrentlyActive = bassLine[stepIndex]?.includes(noteName);
        const newState = !isCurrentlyActive;
        setBassNote(stepIndex, noteName);
        setIsBassDragging(true);
        setBassDragActivationState(newState);
        if (newState && !isPlaying) {
            triggerBassNote(noteName);
        }
    };

    const handleBassCellMouseEnter = (noteName: string, stepIndex: number) => {
        if (isBassDragging) {
            const isCurrentlyActive = bassLine[stepIndex]?.includes(noteName);
            if (bassDragActivationState !== isCurrentlyActive) {
                setBassNote(stepIndex, noteName);
            }
        }
    };

    const incrementTempo = () => setTempo(t => Math.min(MAX_TEMPO, t + 1));
    const decrementTempo = () => setTempo(t => Math.max(MIN_TEMPO, t - 1));

    const incrementSteps = () => {
        const newSteps = steps + 4;
        if (newSteps <= MAX_STEPS) handleStepsChange(newSteps);
    };

    const decrementSteps = () => {
        const newSteps = steps - 4;
        if (newSteps >= MIN_STEPS) handleStepsChange(newSteps);
    };

    return (
        <div className={`p-8 bg-white ${isDragging || isBassDragging ? 'select-none' : ''}`}>
            <Modal
                isOpen={isClearModalOpen}
                onClose={() => setIsClearModalOpen(false)}
                onConfirm={() => { clearPattern(); setIsClearModalOpen(false); }}
                title="Clear Session"
            >
                <p className="text-sm text-slate-500">Are you sure you want to clear the session? This will erase all current progress.</p>
            </Modal>

            {/* Toolbar */}
            <div className="flex items-center justify-between mb-10 pb-6 border-b border-slate-50">
                <div className="flex items-center gap-3">
                    <ControlButton onClick={isPlaying ? stopPlayback : startPlayback} className="min-w-[80px]">
                        {isPlaying ? <><StopIcon className="w-3.5 h-3.5" /> Stop</> : <><PlayIcon className="w-3.5 h-3.5" /> Play</>}
                    </ControlButton>
                    <ControlButton onClick={() => setIsClearModalOpen(true)}>
                        <ClearIcon className="w-3.5 h-3.5" /> Clear
                    </ControlButton>
                </div>

                <div className="flex items-center gap-8">
                    <div className="flex items-center gap-3">
                        <span className="text-[10px] font-bold text-slate-400 uppercase tracking-widest">Tempo</span>
                        <div className="flex items-center bg-slate-50 rounded-lg p-0.5 border border-slate-100">
                            <IconButton onClick={decrementTempo} disabled={tempo <= MIN_TEMPO}><MinusIcon className="w-3.5 h-3.5" /></IconButton>
                            <span className="px-3 text-xs font-black text-slate-700 min-w-[70px] text-center">{tempo} BPM</span>
                            <IconButton onClick={incrementTempo} disabled={tempo >= MAX_TEMPO}><PlusIcon className="w-3.5 h-3.5" /></IconButton>
                        </div>
                    </div>
                    <div className="flex items-center gap-3">
                        <span className="text-[10px] font-bold text-slate-400 uppercase tracking-widest">Steps</span>
                        <div className="flex items-center bg-slate-50 rounded-lg p-0.5 border border-slate-100">
                            <IconButton onClick={decrementSteps} disabled={steps <= MIN_STEPS}><MinusIcon className="w-3.5 h-3.5" /></IconButton>
                            <span className="px-3 text-xs font-black text-slate-700 min-w-[40px] text-center">{steps}</span>
                            <IconButton onClick={incrementSteps} disabled={steps >= MAX_STEPS}><PlusIcon className="w-3.5 h-3.5" /></IconButton>
                        </div>
                    </div>
                </div>

                <div className="flex items-center gap-3">
                    <ControlButton onClick={() => fileInputRef.current?.click()}>
                        <UploadIcon className="w-3.5 h-3.5" /> Import
                    </ControlButton>
                    <input type="file" ref={fileInputRef} onChange={importBeat} accept=".json" className="hidden" />
                    <ControlButton onClick={exportBeat}>
                        <DownloadIcon className="w-3.5 h-3.5" /> Export
                    </ControlButton>
                </div>
            </div>

            {/* Drum Machine Section */}
            <div className="flex gap-10 mb-16">
                <div className="flex flex-col items-center gap-3 shrink-0">
                    <div className="relative h-48 w-6 bg-slate-100 rounded-full border border-slate-200 p-1 flex items-end overflow-hidden">
                        <div
                            className="bg-orange-500 rounded-full w-full transition-all duration-300 shadow-lg shadow-orange-500/30"
                            style={{ height: `${(drumVolume / 1.5) * 100}%` }}
                        ></div>
                        <input
                            type="range" min="0" max="1.5" step="0.01" value={drumVolume}
                            onChange={e => handleDrumVolumeChange(Number(e.target.value))}
                            className="absolute inset-0 opacity-0 cursor-pointer [writing-mode:vertical-lr] [direction:rtl]"
                        />
                        <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none">
                            <div className="w-2.5 h-2.5 bg-white border-2 border-orange-500 rounded-full shadow-md transition-all duration-300" style={{ transform: `translateY(${50 - (drumVolume / 1.5) * 100}%)` }}></div>
                        </div>
                    </div>
                    <span className="text-[9px] font-black text-slate-400 uppercase tracking-[0.2em] [writing-mode:vertical-lr] rotate-180">Drums</span>
                </div>

                <div className="flex-1">
                    <div className="grid gap-x-1.5 gap-y-2" style={{ gridTemplateColumns: `80px repeat(${steps}, 1fr)` }}>
                        {/* Header helper */}
                        <div className="h-6"></div>
                        {Array.from({ length: steps }, (_, i) => (
                            <div key={`d-head-${i}`} className="text-[9px] font-bold text-slate-300 text-center flex items-center justify-center">
                                {i % 4 === 0 ? (i / 4 + 1) : ''}
                            </div>
                        ))}

                        {INSTRUMENTS.map((instrument, instIndex) => (
                            <React.Fragment key={instrument.name}>
                                <div className="flex items-center justify-end pr-4 h-9">
                                    <span className={`text-[11px] font-bold uppercase tracking-widest ${mutes[instIndex] ? 'text-slate-300 line-through' : 'text-slate-500'}`}>
                                        {instrument.name}
                                    </span>
                                </div>
                                {Array.from({ length: steps }).map((_, stepIndex) => {
                                    const isActive = grid[instIndex]?.[stepIndex];
                                    const isCurrent = currentStep === stepIndex;
                                    const isFourth = stepIndex % 4 === 0;
                                    return (
                                        <div
                                            key={`${instrument.name}-${stepIndex}`}
                                            onMouseDown={() => handleCellMouseDown(instIndex, stepIndex)}
                                            onMouseEnter={() => handleCellMouseEnter(instIndex, stepIndex)}
                                            className={`h-9 rounded-sm cursor-pointer transition-all duration-75 relative group overflow-hidden
                                                ${isActive ? 'bg-orange-500 shadow-md shadow-orange-200' : 'bg-slate-100 hover:bg-slate-200'}
                                                ${isCurrent ? 'ring-2 ring-blue-400 ring-offset-1 z-10' : ''}
                                                ${isFourth && stepIndex !== 0 ? 'border-l-2 border-slate-200/50' : ''}
                                            `}
                                        >
                                            {isCurrent && <div className="absolute inset-0 bg-white/20 animate-pulse"></div>}
                                        </div>
                                    )
                                })}
                            </React.Fragment>
                        ))}
                    </div>
                </div>
            </div>

            {/* Bass Section */}
            <div className="flex gap-10">
                <div className="flex flex-col items-center gap-3 shrink-0">
                    <div className="relative h-[400px] w-6 bg-slate-100 rounded-full border border-slate-200 p-1 flex items-end overflow-hidden">
                        <div
                            className="bg-purple-500 rounded-full w-full transition-all duration-300 shadow-lg shadow-purple-500/30"
                            style={{ height: `${(bassVolume / 1) * 100}%` }}
                        ></div>
                        <input
                            type="range" min="0" max="1" step="0.01" value={bassVolume}
                            onChange={e => handleBassVolumeChange(Number(e.target.value))}
                            className="absolute inset-0 opacity-0 cursor-pointer [writing-mode:vertical-lr] [direction:rtl]"
                        />
                        <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none">
                            <div className="w-2.5 h-2.5 bg-white border-2 border-purple-500 rounded-full shadow-md transition-all duration-300" style={{ transform: `translateY(${50 - (bassVolume / 1) * 100}%)` }}></div>
                        </div>
                    </div>
                    <span className="text-[9px] font-black text-slate-400 uppercase tracking-[0.2em] [writing-mode:vertical-lr] rotate-180">Bass</span>
                </div>

                <div className="flex-1">
                    <div className="grid gap-px" style={{ gridTemplateColumns: `80px repeat(${steps}, 1fr)` }}>
                        {/* Header helper */}
                        <div className="h-6"></div>
                        {Array.from({ length: steps }, (_, i) => (
                            <div key={`b-head-${i}`} className="text-[9px] font-bold text-slate-300 text-center flex items-center justify-center">
                                {i % 4 === 0 ? (i / 4 + 1) : ''}
                            </div>
                        ))}

                        {[...BASS_NOTES].reverse().map((note) => (
                            <React.Fragment key={note.name}>
                                <div className={`flex items-center justify-end pr-4 h-5 border-b border-slate-50 ${note.isSharp ? 'bg-slate-50/30' : ''}`}>
                                    <span className={`text-[10px] font-mono ${note.isSharp ? 'text-slate-300 pt-0.5' : 'text-slate-500 font-bold'}`}>
                                        {note.name}
                                    </span>
                                </div>
                                {Array.from({ length: steps }).map((_, stepIndex) => {
                                    const isSelected = bassLine[stepIndex]?.includes(note.name);
                                    const isCurrent = currentStep === stepIndex;
                                    const isFourth = stepIndex % 4 === 0;
                                    return (
                                        <div
                                            key={`${note.name}-${stepIndex}`}
                                            onMouseDown={() => handleBassCellMouseDown(note.name, stepIndex)}
                                            onMouseEnter={() => handleBassCellMouseEnter(note.name, stepIndex)}
                                            className={`h-5 border-b border-r border-slate-50 cursor-pointer transition-all duration-75 relative
                                                ${isSelected ? 'bg-purple-500 shadow-inner' : note.isSharp ? 'bg-slate-50/50 hover:bg-slate-100' : 'bg-white hover:bg-slate-50'}
                                                ${isCurrent ? 'z-10 bg-blue-400/20' : ''}
                                                ${isFourth && stepIndex !== 0 ? 'border-l-2 border-slate-100' : ''}
                                            `}
                                        >
                                            {isCurrent && <div className="absolute inset-0 border-x-2 border-blue-400/50 pointer-events-none"></div>}
                                        </div>
                                    )
                                })}
                            </React.Fragment>
                        ))}
                    </div>
                </div>
            </div>
        </div>
    );
};