import { useEffect, useMemo, useState } from "react";
import { convertFileSrc } from "@tauri-apps/api/core";
import type { HotspotAction } from "../../types/annotations";
import { useEditor } from "./EditorContext";

interface DraftTextInputProps {
    value: string;
    placeholder?: string;
    multiline?: boolean;
    rows?: number;
    className: string;
    onCommit: (value: string) => void;
    onFocus?: () => void;
}

function DraftTextInput({
    value,
    placeholder,
    multiline = false,
    rows = 3,
    className,
    onCommit,
    onFocus,
}: DraftTextInputProps) {
    const [draft, setDraft] = useState(value);

    useEffect(() => {
        setDraft(value);
    }, [value]);

    const commit = () => {
        if (!multiline) {
            const normalized = draft.trim();
            if (normalized === "") {
                setDraft(value);
                return;
            }
            if (normalized === value) {
                setDraft(normalized);
                return;
            }
            onCommit(normalized);
            setDraft(normalized);
            return;
        }
        if (draft === value) return;
        onCommit(draft);
    };

    if (multiline) {
        return (
            <textarea
                value={draft}
                placeholder={placeholder}
                rows={rows}
                className={className}
                onChange={(event) => setDraft(event.target.value)}
                onBlur={commit}
                onFocus={onFocus}
                onKeyDown={(event) => {
                    if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
                        event.preventDefault();
                        commit();
                        event.currentTarget.blur();
                    }
                }}
            />
        );
    }

    return (
        <input
            type="text"
            value={draft}
            placeholder={placeholder}
            className={className}
            onChange={(event) => setDraft(event.target.value)}
            onBlur={commit}
            onFocus={onFocus}
            onKeyDown={(event) => {
                if (event.key === "Enter") {
                    event.preventDefault();
                    commit();
                    event.currentTarget.blur();
                }
            }}
        />
    );
}

const formatRange = (startMs: number, endMs: number): string => {
    const start = Math.max(0, Math.floor(startMs / 1000));
    const end = Math.max(start, Math.floor(endMs / 1000));
    const startMin = Math.floor(start / 60);
    const startSec = start % 60;
    const endMin = Math.floor(end / 60);
    const endSec = end % 60;
    return `${startMin}:${startSec.toString().padStart(2, "0")} - ${endMin}:${endSec
        .toString()
        .padStart(2, "0")}`;
};

const WINDOWS_ABSOLUTE_PATH = /^[a-zA-Z]:[\\/]/;

const isAbsolutePath = (value: string): boolean =>
    value.startsWith("/") || value.startsWith("\\\\") || WINDOWS_ABSOLUTE_PATH.test(value);

const getSessionDirectory = (recordingPath: string | null | undefined): string | null => {
    if (!recordingPath) return null;
    const slash = Math.max(recordingPath.lastIndexOf("/"), recordingPath.lastIndexOf("\\"));
    if (slash < 0) return null;
    return recordingPath.slice(0, slash);
};

const joinPath = (base: string, relative: string): string => {
    const normalizedBase = base.replace(/[\\/]+$/, "");
    const normalizedRelative = relative.replace(/^\.?[\\/]+/, "");
    return `${normalizedBase}/${normalizedRelative}`;
};

const fromFileUrlToPath = (value: string): string => {
    try {
        const url = new URL(value);
        const decoded = decodeURIComponent(url.pathname);
        if (WINDOWS_ABSOLUTE_PATH.test(decoded.slice(1))) {
            return decoded.slice(1);
        }
        return decoded;
    } catch {
        return value.replace(/^file:\/+/, "/");
    }
};

const resolvePreviewSource = (
    path: string | null | undefined,
    recordingPath: string | null | undefined
): string | null => {
    if (!path) return null;
    if (
        path.startsWith("http://") ||
        path.startsWith("https://") ||
        path.startsWith("tauri://") ||
        path.startsWith("asset:") ||
        path.startsWith("blob:") ||
        path.startsWith("data:")
    ) {
        return path;
    }

    const normalizedPath = path.startsWith("file://") ? fromFileUrlToPath(path) : path;
    const filePath =
        isAbsolutePath(normalizedPath) || !recordingPath
            ? normalizedPath
            : (() => {
                  const sessionDir = getSessionDirectory(recordingPath);
                  return sessionDir ? joinPath(sessionDir, normalizedPath) : normalizedPath;
              })();

    try {
        return convertFileSrc(filePath);
    } catch {
        return filePath;
    }
};

const describeAction = (action: HotspotAction): string => {
    if (action.type === "next_step") return "next step";
    if (action.type === "this_step") return "this step";
    if (action.type === "step") return "jump to step";
    if (action.type === "seek") return "seek";
    if (action.type === "url") return "open URL";
    return "none";
};

function EditorScriptView() {
    const {
        metadata,
        steps,
        allHotspots,
        selectedStepId,
        handleSelectStep,
        seekToTimestamp,
        updateStepConfig,
        handleUpdateHotspot,
        handleAnalyzeSession,
        handleGenerateStepsFromActivity,
    } = useEditor();

    const hotspotsById = useMemo(() => {
        return new Map(allHotspots.map((hotspot) => [hotspot.id, hotspot]));
    }, [allHotspots]);

    const sessionTitle = (metadata?.title ?? "").trim() || "Untitled session";

    return (
        <section className="fe-script-layout" aria-label="Script editor">
            <div className="fe-script-scroll">
                <article className="fe-script-doc">
                    <header className="fe-script-header">
                        <p className="fe-script-kicker">Script View</p>
                        <h2>{sessionTitle}</h2>
                        <p>Edit chapter titles, descriptions, and hotspot copy as one document.</p>
                        <div className="fe-script-actions">
                            <button type="button" onClick={() => void handleAnalyzeSession()}>
                                Generate Draft
                            </button>
                            <button type="button" onClick={() => handleGenerateStepsFromActivity()}>
                                Auto Steps from Activity
                            </button>
                        </div>
                    </header>

                    {steps.length === 0 ? (
                        <div className="fe-script-empty">
                            No steps yet. Generate steps, then refine the guide script here.
                        </div>
                    ) : (
                        <ol className="fe-script-chapter-list">
                            {steps.map((step, index) => {
                                const linkedIds = step.hotspot_ids ?? [];
                                const linkedHotspots = linkedIds
                                    .map((id) => hotspotsById.get(id))
                                    .filter((hotspot): hotspot is NonNullable<typeof hotspot> =>
                                        Boolean(hotspot)
                                    );
                                const missingHotspotCount =
                                    linkedIds.length - linkedHotspots.length;
                                const isSelected = step.id === selectedStepId;
                                const previewSrc = resolvePreviewSource(
                                    step.screenshot?.path,
                                    metadata?.recording_path
                                );

                                return (
                                    <li
                                        key={step.id}
                                        className={`fe-script-chapter ${isSelected ? "is-selected" : ""}`}
                                    >
                                        <div className="fe-script-chapter-head">
                                            <button
                                                type="button"
                                                className="fe-script-chapter-jump"
                                                onClick={() => {
                                                    handleSelectStep(step.id);
                                                    seekToTimestamp(step.start_ms / 1000);
                                                }}
                                            >
                                                {index + 1}. Chapter
                                            </button>
                                            <span className="fe-script-chapter-time">
                                                {formatRange(step.start_ms, step.end_ms)}
                                            </span>
                                        </div>

                                        <div className="fe-script-frame-section">
                                            <div className="fe-script-field-label">Frame</div>
                                            <button
                                                type="button"
                                                className="fe-script-frame-preview"
                                                onClick={() => {
                                                    handleSelectStep(step.id);
                                                    seekToTimestamp(step.start_ms / 1000);
                                                }}
                                                aria-label={`Open frame for chapter ${index + 1}`}
                                            >
                                                {previewSrc ? (
                                                    <img
                                                        src={previewSrc}
                                                        alt={`Chapter ${index + 1} frame preview`}
                                                        className="fe-script-frame-image"
                                                    />
                                                ) : (
                                                    <div className="fe-script-frame-empty">
                                                        <svg
                                                            width="20"
                                                            height="20"
                                                            viewBox="0 0 24 24"
                                                            fill="none"
                                                            stroke="currentColor"
                                                            strokeWidth="1.7"
                                                            aria-hidden
                                                        >
                                                            <rect
                                                                x="3"
                                                                y="4"
                                                                width="18"
                                                                height="14"
                                                                rx="2"
                                                            />
                                                            <path d="M8 14l2.2-2.2a1.1 1.1 0 0 1 1.6 0L14 14l1.6-1.6a1.1 1.1 0 0 1 1.6 0L19 14" />
                                                            <path d="M3 20l18-16" />
                                                        </svg>
                                                        <span>Preview unavailable</span>
                                                    </div>
                                                )}
                                            </button>
                                        </div>

                                        <label className="fe-script-field-label">Title</label>
                                        <DraftTextInput
                                            value={step.title}
                                            placeholder="Chapter title"
                                            className="fe-script-input"
                                            onFocus={() => handleSelectStep(step.id)}
                                            onCommit={(nextTitle) => {
                                                updateStepConfig(step.id, (current) => ({
                                                    ...current,
                                                    title: nextTitle.trim() || current.title,
                                                }));
                                            }}
                                        />

                                        <label className="fe-script-field-label">Description</label>
                                        <DraftTextInput
                                            value={step.body ?? ""}
                                            placeholder="Explain what to do in this chapter"
                                            multiline
                                            rows={4}
                                            className="fe-script-textarea"
                                            onFocus={() => handleSelectStep(step.id)}
                                            onCommit={(nextBody) => {
                                                updateStepConfig(step.id, (current) => ({
                                                    ...current,
                                                    body: nextBody,
                                                }));
                                            }}
                                        />

                                        {linkedHotspots.length > 0 && (
                                            <div className="fe-script-hotspots">
                                                <div className="fe-script-hotspots-title">
                                                    Hotspot Copy ({linkedHotspots.length})
                                                </div>
                                                {linkedHotspots.map((hotspot, hotspotIndex) => (
                                                    <div
                                                        key={hotspot.id}
                                                        className="fe-script-hotspot-item"
                                                    >
                                                        <div className="fe-script-hotspot-meta">
                                                            Hotspot {hotspotIndex + 1} ·{" "}
                                                            {hotspot.style} ·{" "}
                                                            {describeAction(hotspot.action)}
                                                        </div>
                                                        <DraftTextInput
                                                            value={hotspot.text ?? ""}
                                                            placeholder="Hotspot text"
                                                            multiline
                                                            rows={2}
                                                            className="fe-script-textarea fe-script-hotspot-input"
                                                            onFocus={() =>
                                                                handleSelectStep(step.id)
                                                            }
                                                            onCommit={(nextText) => {
                                                                handleUpdateHotspot(
                                                                    hotspot.id,
                                                                    (current) => ({
                                                                        ...current,
                                                                        text: nextText,
                                                                    })
                                                                );
                                                            }}
                                                        />
                                                    </div>
                                                ))}
                                            </div>
                                        )}

                                        {missingHotspotCount > 0 && (
                                            <div className="fe-script-warning">
                                                {missingHotspotCount} linked hotspot
                                                {missingHotspotCount === 1 ? "" : "s"} missing.
                                            </div>
                                        )}
                                    </li>
                                );
                            })}
                        </ol>
                    )}
                </article>
            </div>
        </section>
    );
}

export default EditorScriptView;
