"use client";

import { useEffect, useState, useCallback } from "react";
import {
  Modal,
  Form,
  Input,
  InputNumber,
  Select,
  Tabs,
  Button,
  Space,
  App,
} from "antd";
import { PlusOutlined, DeleteOutlined } from "@ant-design/icons";
import { useDebouncedCallback } from "use-debounce";
import { createConfig, updateConfig } from "@/services/config";
import {
  getModrinthLoaders,
  getModrinthEnvironments,
  getCurseForgeMeta,
} from "@/services/meta";
import type { Config, DependencyType, UploadRelationType } from "@/types";

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

const DEPENDENCY_TYPE_LABEL_MAP: Record<DependencyType, string> = {
  required: "Required",
  optional: "Optional",
  incompatible: "Incompatible",
  embedded: "Embedded"
};
const DEPENDENCY_TYPES = Object.entries(DEPENDENCY_TYPE_LABEL_MAP).map(v => ({ value: v[0], label: v[1] }));

const RELATION_TYPE_LABEL_MAP: Record<UploadRelationType, string> = {
  incompatible: "Incompatible",
  embeddedLibrary: "Embedded Library",
  optionalDependency: "Optional Dependency",
  requiredDependency: "Required Dependency",
  tool: "Tool"
};
const RELATION_TYPES = Object.entries(RELATION_TYPE_LABEL_MAP).map(v => ({ value: v[0], label: v[1] }));

// ---------------------------------------------------------------------------
// Data-fetching hooks — each Select loads independently, no blocking
// ---------------------------------------------------------------------------

function useModrinthLoaders(): {
  loading: boolean;
  options: { label: string; value: string }[];
} {
  const [loading, setLoading] = useState(true);
  const [options, setOptions] = useState<{ label: string; value: string }[]>(
    [],
  );

  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    getModrinthLoaders()
      .then((list) => {
        if (!cancelled) {
          setOptions(list.map((l) => ({ label: l, value: l })));
        }
      })
      .catch(() => {})
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, []);

  return { loading, options };
}

function useModrinthEnvironments(): {
  loading: boolean;
  options: { value: string; label: string }[];
} {
  const [loading, setLoading] = useState(true);
  const [options, setOptions] = useState<
    { value: string; label: string }[]
  >([]);

  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    getModrinthEnvironments()
      .then((list) => {
        if (!cancelled) setOptions(list);
      })
      .catch(() => {})
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, []);

  return { loading, options };
}

function useCurseforgeMeta(): {
  loading: boolean;
  environments: string[];
  loaders: string[];
} {
  const [loading, setLoading] = useState(true);
  const [environments, setEnvironments] = useState<string[]>([]);
  const [loaders, setLoaders] = useState<string[]>([]);

  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    getCurseForgeMeta()
      .then((meta) => {
        if (!cancelled) {
          setEnvironments(meta.environments);
          setLoaders(meta.loaders);
        }
      })
      .catch(() => {})
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, []);

  return { loading, environments, loaders };
}

type ConfigValues = Config;

// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------

interface ConfigModalProps {
  open: boolean;
  mode: "add" | "edit";
  initialName: string | null;
  initialConfig: Config | null;
  onCancel: () => void;
  onSaved: (file: string, name: string) => void;
}

export function ConfigModal({
  open,
  mode,
  initialName,
  initialConfig,
  onCancel,
  onSaved,
}: ConfigModalProps) {
  const { message } = App.useApp();
  const [saving, setSaving] = useState(false);

  // --------------- Save ---------------

  const handleSave = useCallback(
    async (values: ConfigValues) => {
      const data: Config = {
        ...values,
        modrinth: {
          ...values.modrinth,
          dependencies: values.modrinth.dependencies ?? [],
        },
        curseforge: {
          ...values.curseforge,
          relations: values.curseforge.relations ?? { projects: [] },
        },
      };

      setSaving(true);
      try {
        if (mode === "add") {
          await createConfig(data);
          onSaved(`${data.name}.json`, data.name);
          message.success("配置已创建");
        } else {
          const oldName = (initialName ?? "").replace(/\.json$/, "");
          await updateConfig(oldName, data);
          onSaved(`${data.name}.json`, data.name);
          message.success("配置已更新");
        }
      } catch (err) {
        message.error(
          err instanceof Error ? err.message : "保存配置失败",
        );
      } finally {
        setSaving(false);
      }
    },
    [mode, initialName, onSaved, message],
  );

  // --------------- Debounced project name lookup ---------------

  const [modrinthProjectName, setModrinthProjectName] = useState<string | null>(null);
  const [curseforgeProjectName, setCurseforgeProjectName] = useState<string | null>(null);

  const lookupModrinthProject = useDebouncedCallback(async (projectId: string) => {
    if (!projectId) {
      setModrinthProjectName(null);
      return;
    }
    // TODO: call Modrinth API to get project name
    setModrinthProjectName(null);
  }, 800);

  const lookupCurseforgeProject = useDebouncedCallback(async (projectId: number | null) => {
    if (projectId == null) {
      setCurseforgeProjectName(null);
      return;
    }
    // TODO: call CurseForge API to get project name
    setCurseforgeProjectName(null);
  }, 800);

  // --------------- Render ---------------

  return (
    <Modal
      title={mode === "add" ? "添加配置" : "修改配置"}
      open={open}
      onCancel={onCancel}
      width={720}
      destroyOnHidden
      footer={
        <Space>
          <Button onClick={onCancel}>取消</Button>
          <Button
            type="primary"
            loading={saving}
            onClick={() => {
              document
                .getElementById("config-modal-submit")
                ?.click();
            }}
          >
            保存
          </Button>
        </Space>
      }
    >
      <ConfigModalForm
        mode={mode}
        initialConfig={initialConfig}
        modrinthProjectName={modrinthProjectName}
        curseforgeProjectName={curseforgeProjectName}
        lookupModrinthProject={lookupModrinthProject}
        lookupCurseforgeProject={lookupCurseforgeProject}
        onSave={handleSave}
      />
    </Modal>
  );
}

// ---------------------------------------------------------------------------
// Inner component — Form with independently-loading Selects
// ---------------------------------------------------------------------------

interface ConfigModalFormProps {
  mode: "add" | "edit";
  initialConfig: Config | null;
  modrinthProjectName: string | null;
  curseforgeProjectName: string | null;
  lookupModrinthProject: (projectId: string) => void;
  lookupCurseforgeProject: (projectId: number | null) => void;
  onSave: (values: ConfigValues) => void;
}

function ConfigModalForm({
  mode,
  initialConfig,
  modrinthProjectName,
  curseforgeProjectName,
  lookupModrinthProject,
  lookupCurseforgeProject,
  onSave,
}: ConfigModalFormProps) {
  const [form] = Form.useForm<ConfigValues>();

  // Each Select loads its own data independently
  const mrLoaders = useModrinthLoaders();
  const mrEnvs = useModrinthEnvironments();
  const cfMeta = useCurseforgeMeta();

  // Reset form when modal opens or mode/config changes
  useEffect(() => {
    if (mode === "edit" && initialConfig) {
      form.setFieldsValue(initialConfig);
    } else {
      form.resetFields();
      form.setFieldsValue({
        minecraft_properties_dir: "./properties",
        project_properties_path: "./gradle.properties",
        mod_version_field: "mod_version",
        filename_format: "",
        source_filename_format: "",
        modrinth: {
          project_id: "",
          version_name:
            "ModName v${version} for Minecraft ${mc_version_range}",
          version: "${version}-mc${mc_version}",
          loaders: [],
          environment: "client_and_server",
          dependencies: [],
        } as Config["modrinth"],
        curseforge: {
          project_id: 0,
          version_name: "#{filename_format}",
          environment: [],
          loaders: [],
          relations: { projects: [] },
        } as Config["curseforge"],
      } as Partial<ConfigValues>);
    }
  }, [mode, initialConfig, form]);

  const handleFinish = useCallback(
    (values: ConfigValues) => {
      onSave(values);
    },
    [onSave],
  );

  const handleFinishFailed = useCallback(() => {}, []);

  return (
    <Form
      form={form}
      layout="vertical"
      onFinish={handleFinish}
      onFinishFailed={handleFinishFailed}
      style={{ maxHeight: "60vh", overflow: "auto", paddingRight: 8 }}
    >
      <button
        id="config-modal-submit"
        type="submit"
        style={{ display: "none" }}
      />

      <Tabs
        items={[
          // ──── 通用 ────
          {
            key: "general",
            label: "通用",
            children: (
              <>
                <Form.Item
                  name="name"
                  label="配置名称"
                  rules={[{ required: true, message: "请输入配置名称" }]}
                >
                  <Input placeholder="模组名称" />
                </Form.Item>

                <Form.Item
                  name="project_dir"
                  label="项目目录"
                  rules={[
                    { required: true, message: "请输入项目目录绝对路径" },
                  ]}
                >
                  <Input placeholder="/path/to/project" />
                </Form.Item>

                <Form.Item
                  name="minecraft_properties_dir"
                  label="MC 属性目录"
                  rules={[{ required: true }]}
                >
                  <Input placeholder="./properties" />
                </Form.Item>

                <Form.Item
                  name="project_properties_path"
                  label="项目属性文件路径"
                  rules={[{ required: true }]}
                >
                  <Input placeholder="./gradle.properties" />
                </Form.Item>

                <Form.Item
                  name="mod_version_field"
                  label="版本号字段名"
                  rules={[{ required: true }]}
                >
                  <Input placeholder="mod_version" />
                </Form.Item>

                <Form.Item
                  name="filename_format"
                  label="构建产物文件名模板"
                  rules={[{ required: true, message: "请输入文件名模板" }]}
                  extra="支持 ${version} 和 ${mc_version} 占位符"
                >
                  <Input placeholder="modname-${version}-mc${mc_version}.jar" />
                </Form.Item>

                <Form.Item
                  name="source_filename_format"
                  label="源码文件名模板"
                  rules={[{ required: true }]}
                  extra="支持 ${version} 和 ${mc_version} 占位符"
                >
                  <Input placeholder="modname-${version}-mc${mc_version}-sources.jar" />
                </Form.Item>
              </>
            ),
          },

          // ──── Modrinth ────
          {
            key: "modrinth",
            label: "Modrinth",
            children: (
              <>
                <Form.Item
                  name={["modrinth", "project_id"]}
                  label="项目 ID"
                  rules={[
                    { required: true, message: "请输入 Modrinth 项目 ID" },
                  ]}
                  extra={
                    modrinthProjectName
                      ? `项目名称: ${modrinthProjectName}`
                      : undefined
                  }
                >
                  <Input
                    placeholder="8 位 base62"
                    onChange={(e) => lookupModrinthProject(e.target.value)}
                  />
                </Form.Item>

                <Form.Item
                  name={["modrinth", "version_name"]}
                  label="版本名称模板"
                  rules={[{ required: true }]}
                  extra="支持 ${version}、${mc_version_range} 等占位符"
                >
                  <Input placeholder="ModName v${version} for Minecraft ${mc_version_range}" />
                </Form.Item>

                <Form.Item
                  name={["modrinth", "version"]}
                  label="版本号模板"
                  rules={[{ required: true }]}
                  extra="支持 ${version}、${mc_version} 等占位符"
                >
                  <Input placeholder="${version}-mc${mc_version}" />
                </Form.Item>

                <Form.Item
                  name={["modrinth", "loaders"]}
                  label="加载器"
                  rules={[{ required: true, message: "请选择加载器" }]}
                >
                  <Select
                    mode="multiple"
                    placeholder="选择加载器…"
                    loading={mrLoaders.loading}
                    options={mrLoaders.options}
                    notFoundContent={
                      mrLoaders.loading ? "加载中…" : "无可用选项"
                    }
                  />
                </Form.Item>

                <Form.Item
                  name={["modrinth", "environment"]}
                  label="运行环境"
                  rules={[{ required: true, message: "请选择运行环境" }]}
                >
                  <Select
                    placeholder="选择运行环境"
                    loading={mrEnvs.loading}
                    options={mrEnvs.options}
                    notFoundContent={
                      mrEnvs.loading ? "加载中…" : "无可用选项"
                    }
                  />
                </Form.Item>

                {/* Dependencies */}
                <Form.Item label="依赖">
                  <Form.List name={["modrinth", "dependencies"]}>
                    {(fields, { add, remove }) => (
                      <>
                        {fields.map(({ key, name, ...rest }) => (
                          <Space
                            key={key}
                            style={{ display: "flex", marginBottom: 8 }}
                            align="baseline"
                          >
                            <Form.Item
                              {...rest}
                              name={[name, "dependency_type"]}
                              rules={[{ required: true, message: "必填" }]}
                              style={{ marginBottom: 0 }}
                            >
                              <Select
                                placeholder="类型"
                                options={DEPENDENCY_TYPES}
                                style={{ width: 140 }}
                              />
                            </Form.Item>
                            <Form.Item
                              {...rest}
                              name={[name, "project_id"]}
                              rules={[{ required: true, message: "必填" }]}
                              style={{ marginBottom: 0 }}
                            >
                              <Input
                                placeholder="项目 ID"
                                style={{ width: 200 }}
                              />
                            </Form.Item>
                            <DeleteOutlined onClick={() => remove(name)} />
                          </Space>
                        ))}
                        <Button
                          type="dashed"
                          onClick={() =>
                            add({
                              dependency_type: "required",
                              project_id: "",
                            })
                          }
                          icon={<PlusOutlined />}
                          block
                        >
                          添加依赖
                        </Button>
                      </>
                    )}
                  </Form.List>
                </Form.Item>
              </>
            ),
          },

          // ──── CurseForge ────
          {
            key: "curseforge",
            label: "CurseForge",
            children: (
              <>
                <Form.Item
                  name={["curseforge", "project_id"]}
                  label="项目 ID"
                  rules={[
                    {
                      required: true,
                      message: "请输入 CurseForge 项目 ID",
                    },
                  ]}
                  extra={
                    curseforgeProjectName
                      ? `项目名称: ${curseforgeProjectName}`
                      : undefined
                  }
                >
                  <InputNumber
                    style={{ width: "100%" }}
                    placeholder="数字 ID"
                    onChange={(val) =>
                      lookupCurseforgeProject(
                        typeof val === "number" ? val : null,
                      )
                    }
                  />
                </Form.Item>

                <Form.Item
                  name={["curseforge", "version_name"]}
                  label="版本名称模板"
                  rules={[{ required: true }]}
                  extra="支持 #{filename_format} 等占位符"
                >
                  <Input placeholder="#{filename_format}" />
                </Form.Item>

                <Form.Item
                  name={["curseforge", "environment"]}
                  label="运行环境"
                  rules={[{ required: true, message: "请选择运行环境" }]}
                >
                  <Select
                    mode="multiple"
                    placeholder="选择运行环境…"
                    loading={cfMeta.loading}
                    options={cfMeta.environments.map((e) => ({
                      label: e,
                      value: e,
                    }))}
                    notFoundContent={
                      cfMeta.loading ? "加载中…" : "无可用选项"
                    }
                  />
                </Form.Item>

                <Form.Item
                  name={["curseforge", "loaders"]}
                  label="加载器"
                  rules={[{ required: true, message: "请选择加载器" }]}
                >
                  <Select
                    mode="multiple"
                    placeholder="选择加载器…"
                    loading={cfMeta.loading}
                    options={cfMeta.loaders.map((l) => ({
                      label: l,
                      value: l,
                    }))}
                    notFoundContent={
                      cfMeta.loading ? "加载中…" : "无可用选项"
                    }
                  />
                </Form.Item>

                {/* Relations */}
                <Form.Item label="关联项目">
                  <Form.List
                    name={["curseforge", "relations", "projects"]}
                  >
                    {(fields, { add, remove }) => (
                      <>
                        {fields.map(({ key, name, ...rest }) => (
                          <Space
                            key={key}
                            style={{ display: "flex", marginBottom: 8 }}
                            align="baseline"
                          >
                            <Form.Item
                              {...rest}
                              name={[name, "slug"]}
                              rules={[{ required: true, message: "必填" }]}
                              style={{ marginBottom: 0 }}
                            >
                              <Input
                                placeholder="Slug"
                                style={{ width: 160 }}
                              />
                            </Form.Item>
                            <Form.Item
                              {...rest}
                              name={[name, "type"]}
                              rules={[{ required: true, message: "必填" }]}
                              style={{ marginBottom: 0 }}
                            >
                              <Select
                                placeholder="类型"
                                options={RELATION_TYPES}
                                style={{ width: 200 }}
                              />
                            </Form.Item>
                            <DeleteOutlined
                              onClick={() => remove(name)}
                            />
                          </Space>
                        ))}
                        <Button
                          type="dashed"
                          onClick={() =>
                            add({ slug: "", type: "requiredDependency" })
                          }
                          icon={<PlusOutlined />}
                          block
                        >
                          添加关联项目
                        </Button>
                      </>
                    )}
                  </Form.List>
                </Form.Item>
              </>
            ),
          },
        ]}
      />
    </Form>
  );
}
