import React, { useCallback, useEffect, useMemo, useState } from "react";
import { Box, Button, Chip, CircularProgress, Paper, Stack, TextField, Typography } from "@mui/material";
import { api, getApiErrorMessage } from "../api";
import { CreatedSuggestedGmailJobResult, GmailManualSyncResult, GmailReviewQueueResponse, GmailSuggestedJobsResponse } from "../types";
import { useToast } from "../toast";
import { useNavigate } from "react-router-dom";

export default function GmailReviewPage({ embedded = false }: { embedded?: boolean }) {
  const { toast } = useToast();
  const navigate = useNavigate();
  const [data, setData] = useState<GmailReviewQueueResponse | null>(null);
  const [suggestions, setSuggestions] = useState<GmailSuggestedJobsResponse | null>(null);
  const [loading, setLoading] = useState(false);
  const [syncing, setSyncing] = useState(false);
  const [savingThreadId, setSavingThreadId] = useState<string | null>(null);
  const [creatingThreadId, setCreatingThreadId] = useState<string | null>(null);
  const [routingFilter, setRoutingFilter] = useState<"all" | "auto-link" | "review" | "unmatched" | "suggested" | "linked" | "rejected">("all");
  const [notes, setNotes] = useState<Record<string, string>>({});

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const [reviewRes, suggestedRes] = await Promise.all([
        api.get<GmailReviewQueueResponse>("/gmail/review-candidates"),
        api.get<GmailSuggestedJobsResponse>("/gmail/suggested-jobs"),
      ]);
      setData(reviewRes.data);
      setSuggestions(suggestedRes.data);
      setNotes((prev) => {
        const next = { ...prev };
        for (const thread of reviewRes.data.threads) {
          if (next[thread.threadId] === undefined) next[thread.threadId] = thread.decisionNote || "";
        }
        return next;
      });
    } catch (error) {
      toast(getApiErrorMessage(error, "Failed to load Gmail review candidates."), "error");
    } finally {
      setLoading(false);
    }
  }, [toast]);

  useEffect(() => {
    void load();
  }, [load]);

  const saveDecision = useCallback(async (threadId: string, decision: "linked" | "rejected" | "review" | "suggested", jobApplicationId?: number) => {
    setSavingThreadId(threadId);
    try {
      await api.post("/gmail/review-decision", {
        threadId,
        decision,
        jobApplicationId: decision === "linked" ? jobApplicationId ?? null : null,
        note: notes[threadId]?.trim() || null,
      });
      await load();
      toast(
        decision === "linked"
          ? "Thread linked and imported."
          : decision === "rejected"
            ? "Thread rejected from review."
            : decision === "suggested"
              ? "Thread kept as suggested job material."
              : "Thread returned to review.",
        "success",
      );
    } catch (error) {
      toast(getApiErrorMessage(error, "Failed to save Gmail review decision."), "error");
    } finally {
      setSavingThreadId(null);
    }
  }, [load, notes, toast]);

  const runManualSync = useCallback(async () => {
    setSyncing(true);
    try {
      const res = await api.post<GmailManualSyncResult>("/gmail/manual-sync", {
        lookbackDays: 365,
        maxResultsPerQuery: 8,
        autoImportHighConfidence: true,
        includeSpamTrash: false,
      });
      await load();
      toast(
        `Manual Gmail sync finished: ${res.data.importedThreads} threads linked, ${res.data.reviewThreadCount} review, ${res.data.unmatchedThreadCount} unmatched.`,
        "success",
      );
    } catch (error) {
      toast(getApiErrorMessage(error, "Failed to run Gmail manual sync."), "error");
    } finally {
      setSyncing(false);
    }
  }, [load, toast]);

  const createSuggestedJob = useCallback(async (threadId: string) => {
    const suggestion = suggestions?.items.find((item) => item.threadId === threadId);
    if (!suggestion) return;

    setCreatingThreadId(threadId);
    try {
      const res = await api.post<CreatedSuggestedGmailJobResult>("/gmail/create-suggested-job", {
        threadId,
        companyName: suggestion.companyName || "Unknown company",
        jobTitle: suggestion.suggestedJobTitle || suggestion.subject || "Suggested role",
        recruiterName: suggestion.recruiterName || null,
        recruiterEmail: suggestion.recruiterEmail || null,
        notes: notes[threadId]?.trim() || suggestion.preview || null,
        status: "Applied",
      });
      await load();
      toast(`Created suggested job and imported ${res.data.imported} message${res.data.imported === 1 ? "" : "s"}.`, "success");
      navigate(`/jobs?open=${res.data.jobApplicationId}`);
    } catch (error) {
      toast(getApiErrorMessage(error, "Failed to create the suggested job."), "error");
    } finally {
      setCreatingThreadId(null);
    }
  }, [load, navigate, notes, suggestions?.items, toast]);

  const filteredThreads = useMemo(() => {
    const threads = data?.threads ?? [];
    return routingFilter === "all" ? threads : threads.filter((thread) => thread.routing === routingFilter);
  }, [data?.threads, routingFilter]);

  return (
    <Paper
      sx={{
        mt: 0,
        p: 2,
        borderRadius: 4,
        border: "none",
        boxShadow: "0px 1px 2px 0px rgba(15,23,42,0.04), 0px 8px 24px -12px rgba(15,23,42,0.12)",
      }}
    >
      <Box sx={{ display: "flex", justifyContent: "space-between", gap: 2, alignItems: "center", flexWrap: "wrap", mb: 2 }}>
        <Box>
          <Typography component={embedded ? "h2" : "h1"} variant="h5" sx={{ fontWeight: 900 }}>{embedded ? "Recruitment message review" : "Gmail review queue"}</Typography>
          <Typography variant="body2" sx={{ color: "text.secondary" }}>
            Manual sync, high-confidence auto-linking, medium-confidence review, and suggested jobs from unmatched Gmail threads.
          </Typography>
        </Box>
        <Box sx={{ display: "flex", gap: 1, flexWrap: "wrap" }}>
          <Button variant="contained" onClick={() => void runManualSync()} disabled={syncing}>
            {syncing ? "Syncing..." : "Run manual sync"}
          </Button>
          <Button variant="outlined" onClick={() => void load()} disabled={loading || syncing}>
            {loading ? "Loading..." : "Refresh"}
          </Button>
          {!embedded ? <Button variant="text" onClick={() => navigate("/correspondence")}>Back to inbox</Button> : null}
        </Box>
      </Box>

      <Box sx={{ display: "flex", gap: 1, flexWrap: "wrap", mb: 2 }}>
        <Chip label={`Filter: ${routingFilter}`} variant="outlined" />
        {(["all", "auto-link", "review", "unmatched", "suggested", "linked", "rejected"] as const).map((value) => (
          <Button key={value} size="small" variant={routingFilter === value ? "contained" : "text"} onClick={() => setRoutingFilter(value)}>
            {value}
          </Button>
        ))}
      </Box>

      {data ? (
        <Box sx={{ display: "flex", gap: 1, flexWrap: "wrap", mb: 2 }}>
          <Chip label={`${data.candidateThreadCount} candidate threads`} variant="outlined" />
          <Chip label={`${data.autoLinkThreadCount} auto-link`} color="success" variant="outlined" />
          <Chip label={`${data.reviewThreadCount} review`} color="warning" variant="outlined" />
          <Chip label={`${data.unmatchedThreadCount} unmatched`} variant="outlined" />
          {suggestions?.count ? <Chip label={`${suggestions.count} suggested jobs`} color="secondary" variant="outlined" /> : null}
        </Box>
      ) : null}

      {loading ? <Box sx={{ py: 6, display: "flex", justifyContent: "center" }}><CircularProgress size={28} /></Box> : null}
      {!loading && data && filteredThreads.length === 0 ? <Typography sx={{ color: "text.secondary" }}>No Gmail review candidates match the current filter.</Typography> : null}

      <Stack spacing={1.25}>
        {filteredThreads.map((thread) => {
          const suggestion = (suggestions?.items ?? []).find((item) => item.threadId === thread.threadId);
          return (
            <Paper key={thread.threadId} variant="outlined" sx={{ p: 1.5, borderRadius: 3 }}>
              <Box sx={{ display: "flex", justifyContent: "space-between", gap: 2, flexWrap: "wrap", alignItems: "flex-start" }}>
                <Box sx={{ minWidth: 0, flex: "1 1 420px" }}>
                  <Typography sx={{ fontWeight: 800, overflowWrap: "anywhere" }}>{thread.subject}</Typography>
                  <Typography variant="body2" sx={{ color: "text.secondary" }}>
                    {thread.messageCount} messages · {thread.routing}
                  </Typography>
                  <Box sx={{ display: "flex", gap: 0.75, flexWrap: "wrap", mt: 0.75 }}>
                    {thread.matchedQueries.slice(0, 3).map((query) => (
                      <Chip key={query} size="small" label={query} variant="outlined" />
                    ))}
                    {thread.hasImportedMessages ? <Chip size="small" label="Has imported messages" color="success" variant="outlined" /> : null}
                  </Box>
                  <TextField
                    label="Review notes"
                    value={notes[thread.threadId] ?? ""}
                    onChange={(event) => setNotes((prev) => ({ ...prev, [thread.threadId]: event.target.value }))}
                    size="small"
                    fullWidth
                    multiline
                    minRows={2}
                    sx={{ mt: 1.25 }}
                    placeholder="Why this should link, stay in review, or become a suggested job."
                  />
                  {suggestion ? (
                    <Typography variant="body2" sx={{ color: "text.secondary", mt: 1 }}>
                      Suggested job: {suggestion.companyName || "Unknown company"} · {suggestion.suggestedJobTitle || "Unknown role"}
                    </Typography>
                  ) : null}
                </Box>
                <Box sx={{ display: "flex", gap: 0.75, flexWrap: "wrap", justifyContent: "flex-end" }}>
                  {thread.jobCandidates.slice(0, 2).map((candidate) => (
                    <Chip
                      key={candidate.jobApplicationId}
                      label={`${candidate.companyName} • ${candidate.jobTitle} (${candidate.score})`}
                      variant="outlined"
                      color={candidate.confidence === "high" ? "success" : candidate.confidence === "medium" ? "warning" : "default"}
                    />
                  ))}
                  {thread.jobCandidates[0] ? (
                    <Button size="small" variant="text" onClick={() => navigate(`/jobs?open=${thread.jobCandidates[0].jobApplicationId}`)}>
                      Open top job
                    </Button>
                  ) : null}
                  {thread.jobCandidates[0] ? (
                    <Button
                      size="small"
                      variant="contained"
                      disabled={savingThreadId === thread.threadId}
                      onClick={() => void saveDecision(thread.threadId, "linked", thread.jobCandidates[0].jobApplicationId)}
                    >
                      Link top job
                    </Button>
                  ) : null}
                  <Button
                    size="small"
                    variant="outlined"
                    color="warning"
                    disabled={savingThreadId === thread.threadId}
                    onClick={() => void saveDecision(thread.threadId, "review")}
                  >
                    Keep in review
                  </Button>
                  <Button
                    size="small"
                    variant="outlined"
                    color="secondary"
                    disabled={savingThreadId === thread.threadId}
                    onClick={() => void saveDecision(thread.threadId, "suggested")}
                  >
                    Suggested job
                  </Button>
                  {suggestion ? (
                    <Button
                      size="small"
                      variant="outlined"
                      disabled={creatingThreadId === thread.threadId}
                      onClick={() => void createSuggestedJob(thread.threadId)}
                    >
                      {creatingThreadId === thread.threadId ? "Creating..." : "Create job"}
                    </Button>
                  ) : null}
                  <Button
                    size="small"
                    variant="outlined"
                    color="error"
                    disabled={savingThreadId === thread.threadId}
                    onClick={() => void saveDecision(thread.threadId, "rejected")}
                  >
                    Reject
                  </Button>
                </Box>
              </Box>
            </Paper>
          );
        })}
      </Stack>
    </Paper>
  );
}
