"use client";

import Link from "next/link";
import { useParams } from "next/navigation";
import { useEffect, useMemo, useState } from "react";

import { CodeEditor } from "@/components/code-editor";
import { MarkdownRenderer } from "@/components/markdown-renderer";
import { apiFetch } from "@/lib/api";
import { readToken } from "@/lib/auth";

type Problem = {
  id: number;
  title: string;
  statement_md: string;
  difficulty: number;
  source: string;
  statement_url: string;
  llm_profile_json: string;
  sample_input: string;
  sample_output: string;
};

type LlmProfile = {
  title?: string;
  difficulty?: number;
  answer?: string;
  explanation?: string;
  knowledge_points?: string[];
  tags?: string[];
  statement_summary_md?: string;
};

type Submission = {
  id: number;
  status: string;
  score: number;
  compile_log: string;
  runtime_log: string;
  created_at: number;
};

type RunResult = {
  status: string;
  time_ms: number;
  stdout: string;
  stderr: string;
  compile_log: string;
};

type DraftResp = {
  language: string;
  code: string;
  stdin: string;
  updated_at: number;
};

type SolutionItem = {
  id: number;
  problem_id: number;
  variant: number;
  title: string;
  idea_md: string;
  explanation_md: string;
  code_cpp: string;
  complexity: string;
  tags_json: string;
  source: string;
  created_at: number;
  updated_at: number;
};

type SolutionJob = {
  id: number;
  problem_id: number;
  status: string;
  progress: number;
  message: string;
  created_at: number;
  started_at: number | null;
  finished_at: number | null;
};

type SolutionResp = {
  items: SolutionItem[];
  latest_job: SolutionJob | null;
  runner_running: boolean;
};

const starterCode = `#include <bits/stdc++.h>
using namespace std;

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  return 0;
}
`;

const defaultRunInput = `1 2\n`;

export default function ProblemDetailPage() {
  const params = useParams<{ id: string }>();
  const id = useMemo(() => Number(params.id), [params.id]);

  const [problem, setProblem] = useState<Problem | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");

  const [code, setCode] = useState(starterCode);
  const [runInput, setRunInput] = useState(defaultRunInput);
  const [contestId, setContestId] = useState("");
  const [submitLoading, setSubmitLoading] = useState(false);
  const [runLoading, setRunLoading] = useState(false);
  const [draftLoading, setDraftLoading] = useState(false);
  const [submitResp, setSubmitResp] = useState<Submission | null>(null);
  const [runResp, setRunResp] = useState<RunResult | null>(null);
  const [draftMsg, setDraftMsg] = useState("");

  const [showSolutions, setShowSolutions] = useState(false);
  const [solutionLoading, setSolutionLoading] = useState(false);
  const [solutionData, setSolutionData] = useState<SolutionResp | null>(null);
  const [solutionMsg, setSolutionMsg] = useState("");

  const llmProfile = useMemo<LlmProfile | null>(() => {
    if (!problem?.llm_profile_json) return null;
    try {
      const parsed = JSON.parse(problem.llm_profile_json);
      return typeof parsed === "object" && parsed !== null ? (parsed as LlmProfile) : null;
    } catch {
      return null;
    }
  }, [problem?.llm_profile_json]);

  useEffect(() => {
    const load = async () => {
      if (!Number.isFinite(id) || id <= 0) return;
      setLoading(true);
      setError("");
      try {
        const data = await apiFetch<Problem>(`/api/v1/problems/${id}`);
        setProblem(data);
      } catch (e: unknown) {
        setError(String(e));
      } finally {
        setLoading(false);
      }
    };
    void load();
  }, [id]);

  useEffect(() => {
    const loadDraft = async () => {
      if (!Number.isFinite(id) || id <= 0) return;
      const token = readToken();
      if (!token) return;
      try {
        const draft = await apiFetch<DraftResp>(`/api/v1/problems/${id}/draft`, undefined, token);
        if (draft.code) setCode(draft.code);
        if (draft.stdin) setRunInput(draft.stdin);
        setDraftMsg("已自动加载草稿");
      } catch {
        // ignore empty draft / unauthorized
      }
    };
    void loadDraft();
  }, [id]);

  const submit = async () => {
    setSubmitLoading(true);
    setSubmitResp(null);
    setError("");
    try {
      const token = readToken();
      if (!token) throw new Error("请先登录后再提交评测");

      const body: Record<string, unknown> = {
        language: "cpp",
        code,
      };
      if (contestId) body.contest_id = Number(contestId);

      const resp = await apiFetch<Submission>(
        `/api/v1/problems/${id}/submit`,
        {
          method: "POST",
          body: JSON.stringify(body),
        },
        token
      );
      setSubmitResp(resp);
    } catch (e: unknown) {
      setError(String(e));
    } finally {
      setSubmitLoading(false);
    }
  };

  const runCode = async () => {
    setRunLoading(true);
    setRunResp(null);
    setError("");
    try {
      const resp = await apiFetch<RunResult>("/api/v1/run/cpp", {
        method: "POST",
        body: JSON.stringify({ code, input: runInput }),
      });
      setRunResp(resp);
    } catch (e: unknown) {
      setError(String(e));
    } finally {
      setRunLoading(false);
    }
  };

  const saveDraft = async () => {
    setDraftLoading(true);
    setDraftMsg("");
    setError("");
    try {
      const token = readToken();
      if (!token) throw new Error("请先登录后再保存草稿");
      await apiFetch<{ saved: boolean }>(
        `/api/v1/problems/${id}/draft`,
        {
          method: "PUT",
          body: JSON.stringify({ language: "cpp", code, stdin: runInput }),
        },
        token
      );
      setDraftMsg("草稿已保存");
    } catch (e: unknown) {
      setError(String(e));
    } finally {
      setDraftLoading(false);
    }
  };

  const loadSolutions = async () => {
    setSolutionLoading(true);
    setSolutionMsg("");
    try {
      const resp = await apiFetch<SolutionResp>(`/api/v1/problems/${id}/solutions`);
      setSolutionData(resp);
    } catch (e: unknown) {
      setSolutionMsg(`加载题解失败：${String(e)}`);
    } finally {
      setSolutionLoading(false);
    }
  };

  const triggerSolutions = async () => {
    setSolutionLoading(true);
    setSolutionMsg("");
    try {
      const token = readToken();
      if (!token) throw new Error("请先登录后再触发题解生成");
      await apiFetch<{ started: boolean; job_id: number }>(
        `/api/v1/problems/${id}/solutions/generate`,
        {
          method: "POST",
          body: JSON.stringify({ max_solutions: 3 }),
        },
        token
      );
      setSolutionMsg("题解生成任务已提交，后台异步处理中...");
      await loadSolutions();
    } catch (e: unknown) {
      setSolutionMsg(`提交失败：${String(e)}`);
    } finally {
      setSolutionLoading(false);
    }
  };

  useEffect(() => {
    if (!showSolutions) return;
    void loadSolutions();
    const timer = setInterval(() => {
      void loadSolutions();
    }, 5000);
    return () => clearInterval(timer);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [showSolutions, id]);

  return (
    <main className="mx-auto max-w-[1400px] px-6 py-8">
      <h1 className="text-2xl font-semibold">题目详情与评测</h1>

      {loading && <p className="mt-4 text-sm text-zinc-500">加载中...</p>}
      {error && <p className="mt-4 text-sm text-red-600">{error}</p>}

      {problem && (
        <div className="mt-4 grid gap-4 lg:grid-cols-[1.1fr,1fr]">
          <section className="rounded-xl border bg-white p-5">
            <h2 className="text-xl font-medium">{problem.title}</h2>
            <p className="mt-1 text-sm text-zinc-600">
              难度 {problem.difficulty} · 来源 {problem.source}
            </p>
            {problem.statement_url && (
              <p className="mt-1 text-sm">
                <a
                  className="text-blue-600 underline"
                  href={problem.statement_url}
                  target="_blank"
                  rel="noreferrer"
                >
                  查看原始题面链接
                </a>
              </p>
            )}

            <div className="mt-4 rounded-lg border bg-zinc-50 p-4">
              <MarkdownRenderer markdown={problem.statement_md} />
            </div>

            {llmProfile?.knowledge_points && llmProfile.knowledge_points.length > 0 && (
              <>
                <h3 className="mt-4 text-sm font-medium">知识点考查</h3>
                <div className="mt-1 flex flex-wrap gap-2">
                  {llmProfile.knowledge_points.map((kp) => (
                    <span key={kp} className="rounded-full bg-zinc-100 px-2 py-1 text-xs">
                      {kp}
                    </span>
                  ))}
                </div>
              </>
            )}

            <h3 className="mt-4 text-sm font-medium">样例输入</h3>
            <pre className="rounded bg-zinc-900 p-3 text-xs text-zinc-100">{problem.sample_input}</pre>

            <h3 className="mt-3 text-sm font-medium">样例输出</h3>
            <pre className="rounded bg-zinc-900 p-3 text-xs text-zinc-100">{problem.sample_output}</pre>
          </section>

          <section className="rounded-xl border bg-white p-5">
            <label className="text-sm font-medium">contest_id（可选）</label>
            <input
              className="mt-1 w-full rounded border px-3 py-2"
              placeholder="例如 1"
              value={contestId}
              onChange={(e) => setContestId(e.target.value)}
            />

            <div className="mt-3 flex flex-wrap items-center gap-2">
              <button
                className="rounded bg-zinc-900 px-4 py-2 text-sm text-white disabled:opacity-50"
                onClick={() => void submit()}
                disabled={submitLoading}
              >
                {submitLoading ? "提交中..." : "提交评测"}
              </button>
              <button
                className="rounded border px-4 py-2 text-sm disabled:opacity-50"
                onClick={() => void saveDraft()}
                disabled={draftLoading}
              >
                {draftLoading ? "保存中..." : "保存草稿"}
              </button>
              <button
                className="rounded border px-4 py-2 text-sm disabled:opacity-50"
                onClick={() => {
                  setShowSolutions((v) => !v);
                }}
                disabled={solutionLoading}
              >
                答案展示
              </button>
            </div>

            {draftMsg && <p className="mt-2 text-xs text-emerald-700">{draftMsg}</p>}

            <label className="mt-4 block text-sm font-medium">C++ 代码（高亮 + 自动提示）</label>
            <div className="mt-1 overflow-hidden rounded border">
              <CodeEditor value={code} onChange={setCode} height="420px" />
            </div>

            <label className="mt-4 block text-sm font-medium">试运行输入</label>
            <textarea
              className="mt-1 h-24 w-full rounded border p-2 font-mono text-xs"
              value={runInput}
              onChange={(e) => setRunInput(e.target.value)}
            />
            <button
              className="mt-2 rounded border px-4 py-2 text-sm disabled:opacity-50"
              onClick={() => void runCode()}
              disabled={runLoading}
            >
              {runLoading ? "试运行中..." : "试运行查看结果"}
            </button>

            {runResp && (
              <div className="mt-3 space-y-2 rounded border p-3 text-xs">
                <p>
                  运行状态：<b>{runResp.status}</b> · 耗时 {runResp.time_ms}ms
                </p>
                {runResp.compile_log && (
                  <pre className="overflow-auto rounded bg-zinc-900 p-2 text-zinc-100">
                    {runResp.compile_log}
                  </pre>
                )}
                <div>
                  <p className="font-medium">stdout</p>
                  <pre className="overflow-auto rounded bg-zinc-900 p-2 text-zinc-100">
                    {runResp.stdout || "(empty)"}
                  </pre>
                </div>
                <div>
                  <p className="font-medium">stderr</p>
                  <pre className="overflow-auto rounded bg-zinc-900 p-2 text-zinc-100">
                    {runResp.stderr || "(empty)"}
                  </pre>
                </div>
              </div>
            )}

            {submitResp && (
              <div className="mt-4 space-y-2 rounded border p-3 text-sm">
                <p>
                  结果：<b>{submitResp.status}</b>，分数 {submitResp.score}
                </p>
                <p>
                  提交 ID：
                  <Link className="ml-1 text-blue-600 underline" href={`/submissions/${submitResp.id}`}>
                    {submitResp.id}
                  </Link>
                </p>
                {submitResp.compile_log && (
                  <pre className="overflow-auto rounded bg-zinc-900 p-2 text-xs text-zinc-100">
                    {submitResp.compile_log}
                  </pre>
                )}
                {submitResp.runtime_log && (
                  <pre className="overflow-auto rounded bg-zinc-900 p-2 text-xs text-zinc-100">
                    {submitResp.runtime_log}
                  </pre>
                )}
              </div>
            )}

            {showSolutions && (
              <div className="mt-5 rounded-lg border bg-zinc-50 p-3">
                <div className="flex flex-wrap items-center gap-2">
                  <h3 className="text-sm font-semibold">官方/LLM 题解</h3>
                  <button
                    className="rounded border px-3 py-1 text-xs disabled:opacity-50"
                    onClick={() => void triggerSolutions()}
                    disabled={solutionLoading}
                  >
                    异步生成多解
                  </button>
                  <button
                    className="rounded border px-3 py-1 text-xs disabled:opacity-50"
                    onClick={() => void loadSolutions()}
                    disabled={solutionLoading}
                  >
                    刷新
                  </button>
                </div>

                {solutionMsg && <p className="mt-2 text-xs text-zinc-600">{solutionMsg}</p>}

                {solutionData?.latest_job && (
                  <p className="mt-2 text-xs text-zinc-600">
                    任务 #{solutionData.latest_job.id} · {solutionData.latest_job.status} ·
                    进度 {solutionData.latest_job.progress}%
                  </p>
                )}

                <div className="mt-3 space-y-3">
                  {(solutionData?.items ?? []).map((item) => (
                    <article key={item.id} className="rounded border bg-white p-3">
                      <h4 className="text-sm font-semibold">
                        解法 {item.variant}：{item.title || "未命名解法"}
                      </h4>
                      {item.complexity && (
                        <p className="mt-1 text-xs text-zinc-600">复杂度：{item.complexity}</p>
                      )}
                      {item.idea_md && (
                        <div className="mt-2 rounded bg-zinc-50 p-2">
                          <MarkdownRenderer markdown={item.idea_md} />
                        </div>
                      )}
                      {item.code_cpp && (
                        <pre className="mt-2 overflow-auto rounded bg-zinc-900 p-2 text-xs text-zinc-100">
                          {item.code_cpp}
                        </pre>
                      )}
                      {item.explanation_md && (
                        <div className="mt-2 rounded bg-zinc-50 p-2">
                          <MarkdownRenderer markdown={item.explanation_md} />
                        </div>
                      )}
                    </article>
                  ))}
                  {!solutionLoading && (solutionData?.items.length ?? 0) === 0 && (
                    <p className="text-xs text-zinc-500">暂无题解，点击“异步生成多解”可触发后台生成。</p>
                  )}
                </div>
              </div>
            )}
          </section>
        </div>
      )}
    </main>
  );
}
