"use client";

import type React from "react";
import { useEffect, useRef } from "react";
import TagInput from "@/components/tag-input";

export type EntryDetailsForm = {
    amountDollars: string;
    occurredAt: string;
    necessity: string;
    notes: string;
    tags: string[];
    entryType: "SPENDING" | "INCOME";
    isRecurring: boolean;
    frequency: "DAILY" | "WEEKLY" | "BIWEEKLY" | "MONTHLY" | "QUARTERLY" | "YEARLY";
    intervalCount: number;
    endCondition: "NEVER" | "AFTER_COUNT" | "BY_DATE";
    endCount: string;
    endDate: string;
};

type EntryDetailsModalProps = {
    isOpen: boolean;
    form: EntryDetailsForm;
    originalForm: EntryDetailsForm | null;
    isDirty: boolean;
    error: string;
    onClose: () => void;
    onSubmit: (event: React.FormEvent<HTMLFormElement>) => void;
    onRequestDelete: () => void;
    onRevert: () => void;
    onChange: (next: Partial<EntryDetailsForm>) => void;
    onAddTag: (tag: string) => void;
    onToggleTag: (tag: string) => void;
    removedTags: string[];
    tagSuggestions: string[];
    emptyTagActionLabel?: string;
    emptyTagActionDisabled?: boolean;
    onEmptyTagAction?: () => void;
    onPrev: () => void;
    onNext: () => void;
    loopHintPrev: string;
    loopHintNext: string;
    canNavigate: boolean;
};

export default function EntryDetailsModal({
    isOpen,
    form,
    originalForm,
    isDirty,
    error,
    onClose,
    onSubmit,
    onRequestDelete,
    onRevert,
    onChange,
    onAddTag,
    onToggleTag,
    removedTags,
    tagSuggestions,
    emptyTagActionLabel,
    emptyTagActionDisabled = false,
    onEmptyTagAction,
    onPrev,
    onNext,
    loopHintPrev,
    loopHintNext,
    canNavigate
}: EntryDetailsModalProps) {
    const baseline = originalForm ?? form;
    const removedSet = new Set(removedTags.map(tag => tag.toLowerCase()));
    const currentTags = form.tags.filter(tag => !removedSet.has(tag.toLowerCase()));
    const normalizeTags = (tags: string[]) => tags.map(tag => tag.toLowerCase()).sort().join("|");
    const baselineTags = baseline.tags || [];
    const tagsChanged = normalizeTags(currentTags) !== normalizeTags(baselineTags);
    const addedTags = currentTags.filter(tag => !baselineTags.some(base => base.toLowerCase() === tag.toLowerCase()));
    const amountChanged = form.amountDollars !== baseline.amountDollars;
    const dateChanged = form.occurredAt !== baseline.occurredAt;
    const necessityChanged = form.necessity !== baseline.necessity;
    const notesChanged = form.notes !== baseline.notes;
    const changedInputClass = "border-2 border-[color:var(--color-accent)]";
    const formRef = useRef<HTMLFormElement | null>(null);

    const touchStartX = useRef<number | null>(null);
    const touchDeltaX = useRef(0);

    function handleTouchStart(event: React.TouchEvent<HTMLDivElement>) {
        touchStartX.current = event.touches[0]?.clientX ?? null;
        touchDeltaX.current = 0;
    }

    function handleTouchMove(event: React.TouchEvent<HTMLDivElement>) {
        if (touchStartX.current === null) return;
        touchDeltaX.current = event.touches[0]?.clientX - touchStartX.current;
    }

    function handleTouchEnd() {
        if (!canNavigate) return;
        const delta = touchDeltaX.current;
        touchStartX.current = null;
        touchDeltaX.current = 0;
        if (Math.abs(delta) < 60) return;
        if (delta > 0) onPrev();
        else onNext();
    }

    useEffect(() => {
        if (!isOpen) return;
        function handleKeyDown(event: KeyboardEvent) {
            if (event.key === "Escape") onClose();
        }
        window.addEventListener("keydown", handleKeyDown);
        return () => window.removeEventListener("keydown", handleKeyDown);
    }, [isOpen, onClose]);

    if (!isOpen) return null;

    return (
        <div
            className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4 !mt-0"
            onClick={onClose}
        >
            <div
                className="relative w-full max-w-xl rounded-xl border border-accent-weak bg-panel p-4"
                onClick={event => event.stopPropagation()}
                onTouchStart={handleTouchStart}
                onTouchMove={handleTouchMove}
                onTouchEnd={handleTouchEnd}
            >
                <div className="grid grid-cols-3 items-center gap-3">
                    <button
                        type="button"
                        onClick={onPrev}
                        className="flex w-24 items-center justify-between rounded-lg border border-accent-weak bg-panel px-2.5 py-1 text-sm font-semibold text-muted hover:border-accent disabled:opacity-50"
                        disabled={!canNavigate}
                        aria-label="Previous entry"
                    >
                        <span aria-hidden>{loopHintPrev ? "↺" : "←"}</span>
                        <span className="text-xs text-soft">{loopHintPrev ? "To Last" : "Prev"}</span>
                    </button>
                    <h2 className="text-center text-lg font-semibold">Entry details</h2>
                    <button
                        type="button"
                        onClick={onNext}
                        className="ml-auto flex w-24 items-center justify-between rounded-lg border border-accent-weak bg-panel px-2.5 py-1 text-sm font-semibold text-muted hover:border-accent disabled:opacity-50"
                        disabled={!canNavigate}
                        aria-label="Next entry"
                    >
                        <span className="text-xs text-soft">{loopHintNext ? "To First" : "Next"}</span>
                        <span aria-hidden>{loopHintNext ? "↻" : "→"}</span>
                    </button>
                </div>
                <form
                    ref={formRef}
                    onSubmit={onSubmit}
                    onKeyDown={event => {
                        if (event.key !== "Enter" || event.defaultPrevented || event.shiftKey) return;
                        const target = event.target as HTMLElement;
                        if (target?.tagName === "TEXTAREA") return;
                        event.preventDefault();
                        formRef.current?.requestSubmit();
                    }}
                    className="mt-3 grid gap-3 md:grid-cols-2"
                >
                    <div className="md:col-span-2 flex flex-wrap items-center gap-2">
                        <button
                            type="button"
                            className={`flex h-9 w-9 items-center justify-center rounded-full border text-lg ${form.isRecurring ? "border-accent bg-accent-soft" : "border-accent-weak bg-panel"}`}
                            onClick={() => onChange({ isRecurring: !form.isRecurring })}
                            title="Toggle Recurring Entry"
                            aria-label={form.isRecurring ? "Recurring entry" : "One-time entry"}
                        >
                            <span aria-hidden>⟳</span>
                        </button>
                        <div className="flex items-center gap-2 rounded-full border border-accent-weak bg-panel">
                            <button
                                type="button"
                                className={`rounded-full px-4 py-2.5 text-xs font-semibold ${form.entryType === "SPENDING" ? "btn-accent" : "text-muted"}`}
                                onClick={() => onChange({ entryType: form.entryType === "SPENDING" ? "INCOME" : "SPENDING" })}
                            >
                                Spending
                            </button>
                            <button
                                type="button"
                                className={`rounded-full px-4 py-2.5 text-xs font-semibold ${form.entryType === "INCOME" ? "btn-accent" : "text-muted"}`}
                                onClick={() => onChange({ entryType: form.entryType === "INCOME" ? "SPENDING" : "INCOME" })}
                            >
                                Income
                            </button>
                        </div>
                    </div>
                    <label className="text-sm text-muted">
                        Amount ($)
                        <input
                            name="amountDollars"
                            type="number"
                            min={0}
                            step="0.01"
                            className={`mt-1 w-full input-base px-3 py-2 text-sm ${amountChanged ? changedInputClass : ""} ${form.amountDollars ? "" : "border-red-400/70"}`}
                            value={form.amountDollars}
                            onChange={e => onChange({ amountDollars: e.target.value })}
                            required
                        />
                    </label>
                    <div className="text-sm text-muted">
                        <input
                            name="occurredAt"
                            type="date"
                            className={`no-date-icon mt-6 w-full input-base px-3 py-2 text-sm ${dateChanged ? changedInputClass : ""} ${form.occurredAt ? "" : "border-red-400/70"}`}
                            value={form.occurredAt}
                            onChange={e => onChange({ occurredAt: e.target.value })}
                            required
                        />
                    </div>
                    <div className="text-sm text-muted">
                        <div className={`mt-6 flex items-center gap-2 rounded-full border border-accent-weak bg-panel ${necessityChanged ? changedInputClass : ""}`} role="group" aria-label="Necessity">
                            {([
                                { value: "NECESSARY", label: "Necessary" },
                                { value: "BOTH", label: "Both" },
                                { value: "UNNECESSARY", label: "Unnecessary" }
                            ] as const).map(option => (
                                <button
                                    key={option.value}
                                    type="button"
                                    className={`flex-1 rounded-full px-3 py-2.5 text-xs font-semibold ${form.necessity === option.value ? "btn-accent" : "text-muted"}`}
                                    onClick={() => onChange({ necessity: option.value })}
                                >
                                    {option.label}
                                </button>
                            ))}
                        </div>
                    </div>
                    <TagInput
                        label="Tags"
                        tags={form.tags}
                        removedTags={removedTags}
                        highlightTags={addedTags}
                        suggestions={tagSuggestions}
                        allowCustom={false}
                        chipsBelow
                        onToggleTag={onToggleTag}
                        onAddTag={onAddTag}
                        emptySuggestionLabel={emptyTagActionLabel}
                        emptySuggestionDisabled={emptyTagActionDisabled}
                        onEmptySuggestionClick={onEmptyTagAction}
                        invalid={!currentTags.length}
                    />
                    {form.isRecurring ? (
                        <div className="md:col-span-2">
                            <div className="text-sm text-muted">Frequency Conditions</div>
                            <div className="mt-2 flex flex-wrap items-center justify-center gap-2">
                                <input
                                    type="number"
                                    min={1}
                                    className="w-20 input-base px-3 py-2 text-center text-sm"
                                    value={form.intervalCount}
                                    onChange={e => onChange({ intervalCount: Number(e.target.value || 1) })}
                                />
                                <select
                                    className="min-w-[120px] input-base px-3 py-2 text-center text-sm"
                                    value={form.frequency}
                                    onChange={e => onChange({ frequency: e.target.value as EntryDetailsForm["frequency"] })}
                                >
                                    <option value="DAILY">day(s)</option>
                                    <option value="WEEKLY">week(s)</option>
                                    <option value="BIWEEKLY">biweekly</option>
                                    <option value="MONTHLY">month(s)</option>
                                    <option value="QUARTERLY">quarter(s)</option>
                                    <option value="YEARLY">year(s)</option>
                                </select>
                                <div className="flex items-center gap-1 rounded-full border border-accent-weak bg-panel" role="group" aria-label="End condition">
                                    {([
                                        { value: "NEVER", label: "Forever" },
                                        { value: "BY_DATE", label: "Until" },
                                        { value: "AFTER_COUNT", label: "After" }
                                    ] as const).map(option => (
                                        <button
                                            key={option.value}
                                            type="button"
                                            className={`rounded-full px-3 py-2 text-xs font-semibold ${form.endCondition === option.value ? "btn-accent" : "text-muted"}`}
                                            onClick={() => onChange({ endCondition: option.value })}
                                        >
                                            {option.label}
                                        </button>
                                    ))}
                                </div>
                                {form.endCondition === "AFTER_COUNT" ? (
                                    <input
                                        type="number"
                                        min={1}
                                        className="w-24 input-base px-3 py-2 text-center text-sm"
                                        value={form.endCount}
                                        placeholder="Count"
                                        onChange={e => onChange({ endCount: e.target.value })}
                                    />
                                ) : null}
                                {form.endCondition === "BY_DATE" ? (
                                    <div className={`inline-flex items-center overflow-hidden rounded-full border ${form.endDate ? "border-accent-weak" : "border-red-400/70"} bg-panel`}>
                                        <button type="button" className="h-11 w-20 text-sm text-muted hover:bg-accent-soft" onClick={() => {
                                            const base = form.endDate ? new Date(form.endDate) : new Date(form.occurredAt || Date.now());
                                            if (Number.isNaN(base.getTime())) return;
                                            base.setDate(base.getDate() - 1);
                                            onChange({ endDate: base.toISOString().slice(0, 10) });
                                        }}>‹</button>
                                        <input
                                            type="date"
                                            className="no-date-icon h-11 w-40 bg-transparent px-3 text-center text-sm text-[color:var(--color-text)] outline-none"
                                            value={form.endDate}
                                            onChange={e => onChange({ endDate: e.target.value })}
                                        />
                                        <button type="button" className="h-11 w-20 text-sm text-muted hover:bg-accent-soft" onClick={() => {
                                            const base = form.endDate ? new Date(form.endDate) : new Date(form.occurredAt || Date.now());
                                            if (Number.isNaN(base.getTime())) return;
                                            base.setDate(base.getDate() + 1);
                                            onChange({ endDate: base.toISOString().slice(0, 10) });
                                        }}>›</button>
                                    </div>
                                ) : null}
                            </div>
                        </div>
                    ) : null}
                    <label className="text-sm text-muted md:col-span-2">
                        Notes
                        <textarea
                            name="notes"
                            className={`mt-1 w-full input-base px-3 py-2 text-sm ${notesChanged ? changedInputClass : ""}`}
                            rows={3}
                            value={form.notes}
                            onChange={e => onChange({ notes: e.target.value })}
                            placeholder="Optional"
                        />
                    </label>
                    <div className="md:col-span-2 flex items-center justify-between">
                        <div className="flex items-center gap-2">
                            <button
                                type="button"
                                onClick={onRevert}
                                disabled={!isDirty}
                                aria-label="Revert changes"
                                className="flex h-9 w-9 items-center justify-center rounded-lg border border-accent-weak bg-panel text-sm hover:border-accent disabled:opacity-40 disabled:cursor-not-allowed"
                            >
                                <svg
                                    aria-hidden="true"
                                    viewBox="0 0 24 24"
                                    className="h-4 w-4"
                                    fill="none"
                                    stroke="currentColor"
                                    strokeWidth="2"
                                    strokeLinecap="round"
                                    strokeLinejoin="round"
                                >
                                    <path d="M3 12a9 9 0 1 0 3-6.7" />
                                    <path d="M3 4v4h4" />
                                </svg>
                            </button>
                            <button
                                type="submit"
                                className="rounded-lg btn-accent px-4 py-2 text-sm font-semibold disabled:opacity-35 disabled:cursor-not-allowed disabled:grayscale disabled:shadow-none"
                                disabled={!isDirty}
                            >
                                Save changes
                            </button>
                            <button
                                type="button"
                                className="rounded-lg btn-outline-accent px-4 py-2 text-sm font-semibold"
                                onClick={onRequestDelete}
                            >
                                Delete
                            </button>

                            <button
                                type="button"
                                onClick={onClose}
                                className="right rounded-lg btn-outline-accent px-4 py-2 text-sm font-semibold"
                                aria-label="Close"
                            >
                                Close
                            </button>
                        </div>
                        {error ? <div className="text-sm text-red-400">{error}</div> : null}
                    </div>
                </form>
            </div>
        </div>
    );
}
