import type { ReactNode } from 'react';
import { useEffect, useMemo, useRef, useState } from 'react';
import type { AutomationScript, ScriptRecordingResult, ScriptSaveInput } from '../../../lib/script-types';
import {
  CheckIcon,
  CloseIcon,
  PlayIcon,
  StopIcon,
} from './icons';

type ScriptDraft = {
  name: string;
  description: string;
  channel: string;
  code: string;
  enabled: boolean;
};

type CreateScriptDialogProps = {
  open: boolean;
  saving: boolean;
  onClose: () => void;
  onSubmit: (input: ScriptSaveInput) => Promise<void>;
};

type EditScriptDialogProps = {
  open: boolean;
  script: AutomationScript | null;
  saving: boolean;
  recordingStatus: 'idle' | 'recording' | 'stopped';
  onClose: () => void;
  onSubmit: (input: ScriptSaveInput) => Promise<void>;
  onStartRecording: (url: string) => Promise<void>;
  onStopRecording: () => Promise<ScriptRecordingResult>;
  onFeedback: (message: string, tone?: 'info' | 'success' | 'error') => void;
};

type ConfirmDeleteDialogProps = {
  open: boolean;
  scriptName?: string;
  deleting: boolean;
  onClose: () => void;
  onConfirm: () => Promise<void>;
};

const CHANNEL_URLS = [
  'https://hotel.fliggy.com/ebooking/hotelBaseInfoUv.htm#/ebk/homeV1',
  'https://me.meituan.com/ebooking/merchant/product#/index',
  'https://life.douyin.com/p/travel-ari/hotel/price_amount_state?groupid=1816249020842116',
];

const DEFAULT_SCRIPT_TEMPLATE = `import { chromium } from 'playwright';
import { preparePage, safeDisconnectBrowser } from './common/tabs.js';

(async () => {
  const browser = await chromium.connectOverCDP('http://127.0.0.1:9222');
  const { page } = await preparePage(browser, {
    targetUrl: 'about:blank',
  });

  // Your automation code here

  await safeDisconnectBrowser(browser);
  process.exit(0);
})();
`;

function buildDefaultScript(channel: string) {
  return DEFAULT_SCRIPT_TEMPLATE.replace('about:blank', channel.trim() || 'about:blank');
}

function ModalFrame({
  open,
  title,
  subtitle,
  widthClassName,
  children,
  onClose,
}: {
  open: boolean;
  title: string;
  subtitle: string;
  widthClassName: string;
  children: ReactNode;
  onClose: () => void;
}) {
  useEffect(() => {
    if (!open) return undefined;

    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        onClose();
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [open, onClose]);

  if (!open) return null;

  return (
    <div
      className="absolute inset-0 z-30 flex items-center justify-center bg-black/30 px-4 py-8 backdrop-blur-[1px]"
      onClick={onClose}
    >
      <div
        className={[
          'max-h-full w-full overflow-hidden rounded-[24px] bg-white  shadow-[0_24px_80px_rgba(15,23,42,0.18)] dark:bg-[#1f1f22]',
          widthClassName,
        ].join(' ')}
        onClick={(event) => event.stopPropagation()}
      >
        <div className="flex items-start justify-between border-b border-black/5 px-6 py-5 dark:border-white/5">
          <div>
            <h2
              className="mb-2 text-[24px] font-normal tracking-tight text-[#171717] dark:text-[#f3f4f6]"
              style={{ fontFamily: "Georgia, Cambria, 'Times New Roman', Times, serif" }}
            >
              {title}
            </h2>
            <p className="text-[14px] text-[#99A0AE] dark:text-gray-500">{subtitle}</p>
          </div>
          <button
            type="button"
            className="rounded-full p-1 text-[#99A0AE] transition-colors hover:text-[#171717] dark:hover:text-[#f3f4f6]"
            onClick={onClose}
            aria-label="关闭"
          >
            <CloseIcon className="h-5 w-5" />
          </button>
        </div>
        <div className="max-h-[calc(100vh-180px)] overflow-y-auto px-6 py-6">
          {children}
        </div>
      </div>
    </div>
  );
}

function FieldLabel({ children }: { children: ReactNode }) {
  return (
    <label className="mb-2 block text-[14px] font-bold text-[#171717]/80 dark:text-[#f3f4f6]/80">
      {children}
    </label>
  );
}

function baseFieldClassName(multiline = false) {
  return [
    'w-full rounded-[14px] border border-transparent bg-[#eceae1] px-4 text-[13px] text-[#171717] outline-none transition-colors',
    'placeholder:text-[#171717]/45 focus:border-[#2B7FFF]/50 dark:bg-[#222225] dark:text-[#f3f4f6] dark:placeholder:text-gray-500',
    multiline ? 'min-h-[108px] py-3 leading-6' : 'h-[46px]',
  ].join(' ');
}

function Switch({
  checked,
  onChange,
  disabled,
}: {
  checked: boolean;
  onChange: (value: boolean) => void;
  disabled?: boolean;
}) {
  return (
    <button
      type="button"
      role="switch"
      aria-checked={checked}
      disabled={disabled}
      onClick={() => onChange(!checked)}
      className={[
        'relative inline-flex h-7 w-12 shrink-0 items-center rounded-full border transition-colors',
        checked ? 'border-[#2B7FFF] bg-[#2B7FFF]' : 'border-black/10 bg-black/10 dark:border-white/10 dark:bg-white/10',
        disabled ? 'cursor-not-allowed opacity-50' : '',
      ].join(' ')}
    >
      <span
        className={[
          'h-5 w-5 rounded-full bg-white shadow-sm transition-transform',
          checked ? 'translate-x-[22px]' : 'translate-x-[3px]',
        ].join(' ')}
      />
    </button>
  );
}

export function CreateScriptDialog({
  open,
  saving,
  onClose,
  onSubmit,
}: CreateScriptDialogProps) {
  const [draft, setDraft] = useState<ScriptDraft>({
    name: '',
    description: '',
    channel: '',
    code: '',
    enabled: true,
  });

  useEffect(() => {
    if (!open) {
      setDraft({
        name: '',
        description: '',
        channel: '',
        code: '',
        enabled: true,
      });
    }
  }, [open]);

  async function handleSubmit() {
    if (!draft.name.trim()) return;

    await onSubmit({
      name: draft.name.trim(),
      description: draft.description.trim(),
      channel: draft.channel.trim(),
      code: buildDefaultScript(draft.channel),
      enabled: true,
    });
  }

  return (
    <ModalFrame
      open={open}
      title="创建脚本"
      subtitle="先创建一个可保存的脚本，再继续录制或编辑 Playwright 代码。"
      widthClassName="max-w-[560px]"
      onClose={onClose}
    >
      <div className="space-y-5">
        <div>
          <FieldLabel>脚本名称</FieldLabel>
          <input
            value={draft.name}
            onChange={(event) => setDraft((current) => ({ ...current, name: event.target.value }))}
            placeholder="例如：飞猪房态采集"
            className={baseFieldClassName()}
          />
        </div>

        <div>
          <FieldLabel>脚本描述</FieldLabel>
          <textarea
            value={draft.description}
            onChange={(event) => setDraft((current) => ({ ...current, description: event.target.value }))}
            placeholder="简要描述这个脚本做什么。"
            className={baseFieldClassName(true)}
          />
        </div>

        <div>
          <FieldLabel>渠道链接</FieldLabel>
          <input
            value={draft.channel}
            onChange={(event) => setDraft((current) => ({ ...current, channel: event.target.value }))}
            placeholder="粘贴目标渠道 URL，可留空后续再补。"
            className={baseFieldClassName()}
          />
          <p className="mt-2 text-[12px] text-[#99A0AE] dark:text-gray-500">
            创建后会尝试启动 codegen，并把录制结果带回编辑器。
          </p>
        </div>

        <div className="flex justify-end gap-3 pt-3">
          <button
            type="button"
            className="inline-flex h-[42px] items-center justify-center rounded-full bg-[#e8e6de] px-6 text-[13px] font-semibold text-[#4B4B4B] transition-colors hover:bg-[#dfddd4] dark:bg-[#222225] dark:text-gray-300 dark:hover:bg-[#2a2a2d]"
            onClick={onClose}
            disabled={saving}
          >
            取消
          </button>
          <button
            type="button"
            className="inline-flex h-[42px] items-center justify-center rounded-full bg-[#2B7FFF] px-6 text-[13px] font-semibold text-white transition-colors hover:bg-[#1769e0] disabled:cursor-wait disabled:opacity-70"
            onClick={() => {
              void handleSubmit();
            }}
            disabled={saving || !draft.name.trim()}
          >
            {saving ? '创建中...' : '创建并录制'}
          </button>
        </div>
      </div>
    </ModalFrame>
  );
}

export function EditScriptDialog({
  open,
  script,
  saving,
  recordingStatus,
  onClose,
  onSubmit,
  onStartRecording,
  onStopRecording,
  onFeedback,
}: EditScriptDialogProps) {
  const [draft, setDraft] = useState<ScriptDraft>({
    name: '',
    description: '',
    channel: '',
    code: '',
    enabled: true,
  });
  const [recordingBusy, setRecordingBusy] = useState(false);
  const previousChannelRef = useRef('');

  useEffect(() => {
    if (!open || !script) return;

    const nextDraft = {
      name: script.name || '',
      description: script.description || '',
      channel: script.channel || '',
      code: script.code || '',
      enabled: script.enabled ?? true,
    };
    setDraft(nextDraft);
    previousChannelRef.current = nextDraft.channel;
  }, [open, script]);

  useEffect(() => {
    const previousChannel = previousChannelRef.current;
    if (!previousChannel || previousChannel === draft.channel) return;

    setDraft((current) => {
      if (!current.code.includes(previousChannel)) {
        previousChannelRef.current = draft.channel;
        return current;
      }

      previousChannelRef.current = draft.channel;
      return {
        ...current,
        code: current.code.split(previousChannel).join(draft.channel),
      };
    });
  }, [draft.channel]);

  const replaceChannelDisabled = useMemo(() => {
    if (!draft.channel.trim()) return true;
    return !CHANNEL_URLS.some((url) => draft.code.includes(url));
  }, [draft.channel, draft.code]);

  if (!script) return null;

  async function handleSave() {
    if (!draft.name.trim() || !draft.code.trim()) return;

    await onSubmit({
      id: script.id,
      name: draft.name.trim(),
      description: draft.description.trim(),
      channel: draft.channel.trim(),
      code: draft.code,
      enabled: draft.enabled,
    });
  }

  async function handleStartRecording() {
    if (!draft.channel.trim()) {
      onFeedback('开始录制前请先填写渠道链接。', 'error');
      return;
    }

    setRecordingBusy(true);
    try {
      await onStartRecording(draft.channel.trim());
    } finally {
      setRecordingBusy(false);
    }
  }

  async function handleStopRecording() {
    setRecordingBusy(true);
    try {
      const result = await onStopRecording();
      if (result.code) {
        setDraft((current) => ({ ...current, code: result.code || current.code }));
      }
    } finally {
      setRecordingBusy(false);
    }
  }

  function replaceKnownChannelUrls() {
    setDraft((current) => ({
      ...current,
      code: CHANNEL_URLS.reduce((source, url) => source.split(url).join(current.channel.trim()), current.code),
    }));
    onFeedback('已将代码中的已知渠道链接替换为当前输入值。', 'success');
  }

  return (
    <ModalFrame
      open={open}
      title="编辑脚本"
      subtitle="修改脚本信息、维护 Playwright 代码，并在需要时重新录制。"
      widthClassName="max-w-[820px]"
      onClose={onClose}
    >
      <div className="space-y-5">
        <div>
          <FieldLabel>脚本名称</FieldLabel>
          <input
            value={draft.name}
            onChange={(event) => setDraft((current) => ({ ...current, name: event.target.value }))}
            placeholder="输入脚本名称"
            className={baseFieldClassName()}
          />
        </div>

        <div>
          <FieldLabel>脚本描述</FieldLabel>
          <textarea
            value={draft.description}
            onChange={(event) => setDraft((current) => ({ ...current, description: event.target.value }))}
            placeholder="补充脚本用途、依赖页面或注意事项。"
            className={baseFieldClassName(true)}
          />
        </div>

        <div>
          <div className="mb-2 flex items-center justify-between gap-3">
            <FieldLabel>渠道链接</FieldLabel>
            <button
              type="button"
              className="text-[12px] font-medium text-[#2B7FFF] transition-colors hover:text-[#1769e0] disabled:cursor-not-allowed disabled:text-[#99A0AE]"
              disabled={replaceChannelDisabled}
              onClick={replaceKnownChannelUrls}
            >
              同步替换代码中的渠道 URL
            </button>
          </div>
          <input
            value={draft.channel}
            onChange={(event) => setDraft((current) => ({ ...current, channel: event.target.value }))}
            placeholder="粘贴渠道 URL"
            className={baseFieldClassName()}
          />
        </div>

        <div>
          <div className="mb-2 flex items-center justify-between gap-3">
            <FieldLabel>脚本代码</FieldLabel>
            <div className="flex items-center gap-2">
              {recordingStatus === 'recording' ? (
                <button
                  type="button"
                  className="inline-flex h-8 items-center justify-center rounded-full bg-red-500 px-4 text-[12px] font-semibold text-white transition-colors hover:bg-red-600 disabled:cursor-wait disabled:opacity-70"
                  onClick={() => {
                    void handleStopRecording();
                  }}
                  disabled={recordingBusy}
                >
                  <StopIcon className="mr-1.5 h-3.5 w-3.5" />
                  {recordingBusy ? '停止中...' : '停止录制'}
                </button>
              ) : (
                <button
                  type="button"
                  className="inline-flex h-8 items-center justify-center rounded-full border border-black/10 px-4 text-[12px] font-semibold text-[#171717] transition-colors hover:bg-black/5 dark:border-gray-700 dark:text-[#f3f4f6] dark:hover:bg-white/5 disabled:cursor-wait disabled:opacity-70"
                  onClick={() => {
                    void handleStartRecording();
                  }}
                  disabled={recordingBusy}
                >
                  <PlayIcon className="mr-1.5 h-3.5 w-3.5" />
                  {recordingBusy ? '启动中...' : '开始录制'}
                </button>
              )}
            </div>
          </div>

          {recordingStatus === 'recording' ? (
            <p className="mb-3 rounded-xl border border-amber-200 bg-amber-50 px-3 py-2 text-[12px] text-amber-700 dark:border-amber-900/60 dark:bg-amber-900/20 dark:text-amber-300">
              录制进行中，请在新窗口中完成操作，结束后点击“停止录制”回填代码。
            </p>
          ) : null}

          <textarea
            value={draft.code}
            onChange={(event) => setDraft((current) => ({ ...current, code: event.target.value }))}
            placeholder="// 在这里编写 Playwright 自动化脚本"
            spellCheck={false}
            className="min-h-[340px] w-full rounded-[18px] border border-transparent bg-[#eceae1] px-4 py-4 font-mono text-[13px] leading-6 text-[#171717] outline-none transition-colors placeholder:text-[#171717]/45 focus:border-[#2B7FFF]/50 dark:bg-[#0f0f10] dark:text-[#f3f4f6] dark:placeholder:text-gray-500"
          />
        </div>

        <div className="flex items-center justify-between rounded-[18px] border border-black/5 bg-[#e8e6de]/60 px-4 py-4 dark:border-white/5 dark:bg-[#222225]">
          <div>
            <p className="text-[14px] font-bold text-[#171717]/80 dark:text-[#f3f4f6]/80">启用脚本</p>
            <p className="mt-1 text-[13px] text-[#99A0AE] dark:text-gray-500">保存后立即保持脚本可用状态。</p>
          </div>
          <Switch checked={draft.enabled} onChange={(value) => setDraft((current) => ({ ...current, enabled: value }))} />
        </div>

        <div className="flex justify-end gap-3 pt-3">
          <button
            type="button"
            className="inline-flex h-[42px] items-center justify-center rounded-full bg-[#e8e6de] px-6 text-[13px] font-semibold text-[#4B4B4B] transition-colors hover:bg-[#dfddd4] dark:bg-[#222225] dark:text-gray-300 dark:hover:bg-[#2a2a2d]"
            onClick={onClose}
            disabled={saving}
          >
            取消
          </button>
          <button
            type="button"
            className="inline-flex h-[42px] items-center justify-center rounded-full bg-[#2B7FFF] px-6 text-[13px] font-semibold text-white transition-colors hover:bg-[#1769e0] disabled:cursor-wait disabled:opacity-70"
            onClick={() => {
              void handleSave();
            }}
            disabled={saving || !draft.name.trim() || !draft.code.trim()}
          >
            <CheckIcon className="mr-1.5 h-4 w-4" />
            {saving ? '保存中...' : '保存修改'}
          </button>
        </div>
      </div>
    </ModalFrame>
  );
}

export function ConfirmDeleteDialog({
  open,
  scriptName,
  deleting,
  onClose,
  onConfirm,
}: ConfirmDeleteDialogProps) {
  return (
    <ModalFrame
      open={open}
      title="删除脚本"
      subtitle="删除后脚本文件也会一并移除，请确认这就是你想要的操作。"
      widthClassName="max-w-[520px]"
      onClose={onClose}
    >
      <div className="space-y-6">
        <div className="rounded-[18px] border border-red-500/20 bg-red-500/8 px-4 py-4 text-[14px] leading-6 text-[#171717] dark:text-gray-200">
          {scriptName ? `确认删除 “${scriptName}” 吗？此操作无法撤销。` : '确认删除这个脚本吗？此操作无法撤销。'}
        </div>

        <div className="flex justify-end gap-3">
          <button
            type="button"
            className="inline-flex h-[42px] items-center justify-center rounded-full bg-[#e8e6de] px-6 text-[13px] font-semibold text-[#4B4B4B] transition-colors hover:bg-[#dfddd4] dark:bg-[#222225] dark:text-gray-300 dark:hover:bg-[#2a2a2d]"
            onClick={onClose}
            disabled={deleting}
          >
            取消
          </button>
          <button
            type="button"
            className="inline-flex h-[42px] items-center justify-center rounded-full bg-red-500 px-6 text-[13px] font-semibold text-white transition-colors hover:bg-red-600 disabled:cursor-wait disabled:opacity-70"
            onClick={() => {
              void onConfirm();
            }}
            disabled={deleting}
          >
            {deleting ? '删除中...' : '确认删除'}
          </button>
        </div>
      </div>
    </ModalFrame>
  );
}

export { Switch };
