import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";

import {
  Box,
  Button,
  Chip,
  CircularProgress,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  Divider,
  List,
  ListItemButton,
  ListItemText,
  Paper,
  Tab,
  Tabs,
  TextField,
  ToggleButton,
  ToggleButtonGroup,
  Typography,
} from "@mui/material";
import { alpha, useTheme } from "@mui/material/styles";

import { api } from "../api";
import { useToast } from "../toast";
import { CorrespondenceMessage, GmailMessageSummary, GmailStatus } from "../types";

function parseRawEmail(raw: string): {
  subject?: string;
  date?: string;
  from?: string;
  to?: string;
  body: string;
} {
  const lines = raw.replace(/\r\n/g, "\n").split("\n");
  const headers: Record<string, string> = {};
  let i = 0;

  for (; i < lines.length; i++) {
    const line = lines[i];
    if (line.trim() === "") {
      i++;
      break;
    }

    const idx = line.indexOf(":");
    if (idx <= 0) continue;

    const k = line.slice(0, idx).trim().toLowerCase();
    const v = line.slice(idx + 1).trim();
    headers[k] = headers[k] ? `${headers[k]} ${v}` : v;
  }

  const body = lines.slice(i).join("\n").trim();
  const subject = headers["subject"];
  const from = headers["from"];
  const to = headers["to"];
  const dateRaw = headers["date"];

  let iso: string | undefined;
  if (dateRaw) {
    const d = new Date(dateRaw);
    if (!Number.isNaN(+d)) iso = d.toISOString();
  }

  return { subject, from, to, date: iso, body };
}

export default function Correspondence({ jobId }: { jobId: number }) {
  const theme = useTheme();
  const { toast } = useToast();
  const [messages, setMessages] = useState<CorrespondenceMessage[]>([]);
  const [from, setFrom] = useState<"Me" | "Company">("Me");
  const [text, setText] = useState("");
  const scrollRef = useRef<HTMLDivElement | null>(null);

  const [importOpen, setImportOpen] = useState(false);
  const [importTab, setImportTab] = useState(0);
  const [rawEmail, setRawEmail] = useState("");

  const [gmailStatus, setGmailStatus] = useState<GmailStatus | null>(null);
  const [gmailLoading, setGmailLoading] = useState(false);
  const [gmailQuery, setGmailQuery] = useState("");
  const [gmailMessages, setGmailMessages] = useState<GmailMessageSummary[]>([]);
  const [gmailMessagesLoading, setGmailMessagesLoading] = useState(false);
  const [importingMessageId, setImportingMessageId] = useState<string | null>(null);

  const load = useCallback(async () => {
    const res = await api.get<CorrespondenceMessage[]>(`/correspondence/${jobId}`);
    setMessages(res.data);
  }, [jobId]);

  const loadGmailStatus = useCallback(async () => {
    try {
      setGmailLoading(true);
      const res = await api.get<GmailStatus>("/gmail/status");
      setGmailStatus(res.data);
    } catch {
      setGmailStatus({ connected: false });
    } finally {
      setGmailLoading(false);
    }
  }, []);

  const loadGmailMessages = useCallback(async () => {
    try {
      setGmailMessagesLoading(true);
      const res = await api.get<GmailMessageSummary[]>("/gmail/messages", {
        params: {
          query: gmailQuery.trim() || undefined,
          maxResults: 12,
        },
      });
      setGmailMessages(res.data);
    } catch (error: any) {
      const message =
        error?.response?.data && typeof error.response.data === "string"
          ? error.response.data
          : "Failed to load Gmail messages.";
      toast(message, "error");
    } finally {
      setGmailMessagesLoading(false);
    }
  }, [gmailQuery, toast]);

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

  useEffect(() => {
    const el = scrollRef.current;
    if (!el) return;
    el.scrollTop = el.scrollHeight;
  }, [messages.length]);

  useEffect(() => {
    if (!importOpen) return;
    void loadGmailStatus();
  }, [importOpen, loadGmailStatus]);

  useEffect(() => {
    if (!importOpen || importTab !== 1 || !gmailStatus?.connected) return;
    void loadGmailMessages();
  }, [importOpen, importTab, gmailStatus?.connected, loadGmailMessages]);

  useEffect(() => {
    const onMessage = (event: MessageEvent) => {
      const data = event.data as { source?: string; status?: string; message?: string };
      if (data?.source !== "jobtracker-gmail-oauth") return;
      if (data.status === "connected") {
        toast(data.message || "Gmail connected.", "success");
        void loadGmailStatus();
        setImportTab(1);
        void loadGmailMessages();
      } else {
        toast(data.message || "Gmail connection failed.", "error");
      }
    };

    window.addEventListener("message", onMessage);
    return () => window.removeEventListener("message", onMessage);
  }, [loadGmailMessages, loadGmailStatus, toast]);

  const canSend = useMemo(() => text.trim().length > 0, [text]);

  const send = async () => {
    if (!canSend) return;

    try {
      await api.post("/correspondence", {
        jobApplicationId: jobId,
        from,
        content: text,
      });

      setText("");
      await load();
    } catch {
      toast("Failed to add message.", "error");
    }
  };

  const importEmail = async () => {
    const parsed = parseRawEmail(rawEmail);
    if (!parsed.body && !parsed.subject && !rawEmail.trim()) {
      toast("Paste an email first.", "error");
      return;
    }

    try {
      await api.post("/correspondence", {
        jobApplicationId: jobId,
        from,
        channel: "Email",
        subject: parsed.subject ?? null,
        content: parsed.body || rawEmail,
        date: parsed.date ?? null,
      });

      setImportOpen(false);
      setRawEmail("");
      await load();
      toast("Email logged.", "success");
    } catch {
      toast("Failed to import email.", "error");
    }
  };

  const connectGmail = async () => {
    try {
      const res = await api.get<{ url: string }>("/gmail/connect-url");
      const popup = window.open(res.data.url, "jobtracker-gmail-connect", "width=620,height=760,resizable=yes,scrollbars=yes");
      if (!popup) {
        toast("Your browser blocked the Gmail popup.", "error");
      }
    } catch {
      toast("Failed to start Gmail connection.", "error");
    }
  };

  const disconnectGmail = async () => {
    try {
      await api.delete("/gmail/connection");
      setGmailStatus({ connected: false });
      setGmailMessages([]);
      toast("Gmail disconnected.", "success");
    } catch {
      toast("Failed to disconnect Gmail.", "error");
    }
  };

  const importGmailMessage = async (messageId: string) => {
    try {
      setImportingMessageId(messageId);
      await api.post("/gmail/import", {
        jobApplicationId: jobId,
        messageId,
      });
      await load();
      toast("Email imported from Gmail.", "success");
    } catch (error: any) {
      const message =
        error?.response?.data && typeof error.response.data === "string"
          ? error.response.data
          : "Failed to import Gmail message.";
      toast(message, "error");
    } finally {
      setImportingMessageId(null);
    }
  };

  return (
    <Box>
      <Paper
        ref={scrollRef}
        sx={{
          p: 1.5,
          maxHeight: 360,
          overflowY: "auto",
          background:
            theme.palette.mode === "dark"
              ? "rgba(15,23,42,0.45)"
              : "rgba(255,255,255,0.75)",
          backdropFilter: "blur(8px)",
        }}
      >
        {messages.length === 0 ? (
          <Typography sx={{ color: "text.secondary", py: 2, textAlign: "center" }}>
            No messages yet.
          </Typography>
        ) : (
          <Box sx={{ display: "flex", flexDirection: "column", gap: 1 }}>
            {messages.map((m) => {
              const isMe = (m.from || "").toLowerCase() === "me";
              const accent = isMe ? theme.palette.primary.main : theme.palette.warning.main;
              return (
                <Box
                  key={m.id}
                  sx={{
                    display: "flex",
                    justifyContent: isMe ? "flex-end" : "flex-start",
                  }}
                >
                  <Box
                    sx={{
                      maxWidth: "80%",
                      borderRadius: 3,
                      p: 1.25,
                      border: `1px solid ${alpha(accent, theme.palette.mode === "dark" ? 0.32 : 0.22)}`,
                      background: alpha(accent, theme.palette.mode === "dark" ? 0.14 : 0.1),
                      color: "text.primary",
                    }}
                  >
                    {m.subject ? (
                      <Typography sx={{ fontWeight: 800, mb: 0.5 }}>
                        {m.subject}
                      </Typography>
                    ) : null}

                    <Typography sx={{ whiteSpace: "pre-wrap", lineHeight: 1.35 }}>
                      {m.content}
                    </Typography>

                    <Typography variant="caption" sx={{ display: "block", mt: 0.75, color: "text.secondary" }}>
                      {isMe ? "Me" : "Company"}
                      {m.channel ? ` - ${m.channel}` : ""}
                      {m.date ? ` - ${new Date(m.date).toLocaleString()}` : ""}
                    </Typography>
                  </Box>
                </Box>
              );
            })}
          </Box>
        )}
      </Paper>

      <Box sx={{ display: "flex", gap: 1, alignItems: "center", mt: 1.5, flexWrap: "wrap" }}>
        <ToggleButtonGroup
          exclusive
          value={from}
          onChange={(_, v) => {
            if (v) setFrom(v);
          }}
          size="small"
        >
          <ToggleButton value="Me">Me</ToggleButton>
          <ToggleButton value="Company">Company</ToggleButton>
        </ToggleButtonGroup>

        <Button variant="outlined" size="small" onClick={() => setImportOpen(true)}>
          Import Email
        </Button>

        <Box sx={{ flex: "1 1 280px" }}>
          <textarea
            value={text}
            onChange={(e) => setText(e.target.value)}
            placeholder="Log an email/call note..."
            style={{
              width: "100%",
              minHeight: 70,
              resize: "vertical",
              padding: 10,
              borderRadius: 12,
              border:
                theme.palette.mode === "dark"
                  ? "1px solid rgba(148,163,184,0.25)"
                  : "1px solid rgba(15,23,42,0.12)",
              background: theme.palette.mode === "dark" ? "rgba(2,6,23,0.25)" : "white",
              color: theme.palette.text.primary,
              fontFamily: "inherit",
              fontSize: 14,
            }}
          />
        </Box>

        <Button variant="contained" onClick={send} disabled={!canSend}>
          Add
        </Button>
      </Box>

      <Dialog open={importOpen} onClose={() => setImportOpen(false)} fullWidth maxWidth="md">
        <DialogTitle>Import Email</DialogTitle>
        <DialogContent>
          <Tabs value={importTab} onChange={(_, v) => setImportTab(v)} sx={{ mb: 2 }}>
            <Tab label="Paste email" />
            <Tab label="Gmail" />
          </Tabs>

          {importTab === 0 ? (
            <>
              <Typography sx={{ color: "text.secondary", mb: 1 }}>
                Paste raw email text (headers optional). We parse Subject and Date when present.
              </Typography>
              <textarea
                value={rawEmail}
                onChange={(e) => setRawEmail(e.target.value)}
                placeholder={"Subject: ...\nDate: ...\nFrom: ...\nTo: ...\n\nBody..."}
                style={{
                  width: "100%",
                  minHeight: 220,
                  resize: "vertical",
                  padding: 12,
                  borderRadius: 12,
                  border:
                    theme.palette.mode === "dark"
                      ? "1px solid rgba(148,163,184,0.25)"
                      : "1px solid rgba(15,23,42,0.12)",
                  background: theme.palette.mode === "dark" ? "rgba(2,6,23,0.25)" : "white",
                  color: theme.palette.text.primary,
                  fontFamily: "inherit",
                  fontSize: 14,
                }}
              />
            </>
          ) : (
            <Box sx={{ display: "flex", flexDirection: "column", gap: 2 }}>
              <Box sx={{ display: "flex", justifyContent: "space-between", gap: 1, flexWrap: "wrap", alignItems: "center" }}>
                <Box>
                  <Typography sx={{ fontWeight: 800 }}>Google Gmail</Typography>
                  <Typography variant="body2" sx={{ color: "text.secondary" }}>
                    {gmailLoading
                      ? "Checking connection..."
                      : gmailStatus?.connected
                        ? `Connected as ${gmailStatus.gmailAddress}`
                        : "Connect your Gmail account to browse recent emails."}
                  </Typography>
                </Box>
                <Box sx={{ display: "flex", gap: 1, flexWrap: "wrap" }}>
                  {gmailStatus?.connected ? (
                    <>
                      <Button variant="outlined" onClick={() => void loadGmailMessages()} disabled={gmailMessagesLoading}>
                        Refresh
                      </Button>
                      <Button variant="outlined" color="error" onClick={() => void disconnectGmail()}>
                        Disconnect
                      </Button>
                    </>
                  ) : (
                    <Button variant="contained" onClick={() => void connectGmail()}>
                      Connect Gmail
                    </Button>
                  )}
                </Box>
              </Box>

              {gmailStatus?.connected ? (
                <>
                  <Box sx={{ display: "flex", gap: 1, flexWrap: "wrap", alignItems: "center" }}>
                    <TextField
                      label="Search Gmail"
                      value={gmailQuery}
                      onChange={(e) => setGmailQuery(e.target.value)}
                      placeholder="from:company@example.com OR interview"
                      size="small"
                      fullWidth
                    />
                    <Button variant="outlined" onClick={() => void loadGmailMessages()} disabled={gmailMessagesLoading}>
                      Search
                    </Button>
                  </Box>
                  {gmailStatus.lastSyncedAt ? (
                    <Chip label={`Last synced ${new Date(gmailStatus.lastSyncedAt).toLocaleString()}`} size="small" />
                  ) : null}
                  <Paper variant="outlined" sx={{ maxHeight: 360, overflowY: "auto" }}>
                    {gmailMessagesLoading ? (
                      <Box sx={{ py: 5, display: "flex", justifyContent: "center" }}>
                        <CircularProgress size={28} />
                      </Box>
                    ) : gmailMessages.length === 0 ? (
                      <Typography sx={{ color: "text.secondary", p: 2 }}>No Gmail messages found.</Typography>
                    ) : (
                      <List disablePadding>
                        {gmailMessages.map((message, index) => (
                          <React.Fragment key={message.id}>
                            {index > 0 ? <Divider /> : null}
                            <ListItemButton sx={{ alignItems: "flex-start", py: 1.5 }}>
                              <ListItemText
                                primary={
                                  <Box sx={{ display: "flex", justifyContent: "space-between", gap: 2, alignItems: "center", flexWrap: "wrap" }}>
                                    <Typography sx={{ fontWeight: 800 }}>{message.subject || "(No subject)"}</Typography>
                                    <Typography variant="caption" sx={{ color: "text.secondary" }}>
                                      {message.date ? new Date(message.date).toLocaleString() : ""}
                                    </Typography>
                                  </Box>
                                }
                                secondary={
                                  <Box sx={{ mt: 0.5 }}>
                                    <Typography variant="body2" sx={{ color: "text.primary" }}>
                                      From: {message.from || "Unknown"}
                                    </Typography>
                                    <Typography variant="body2" sx={{ color: "text.secondary", mt: 0.25 }}>
                                      {message.snippet}
                                    </Typography>
                                  </Box>
                                }
                              />
                              <Button
                                variant="contained"
                                size="small"
                                disabled={importingMessageId === message.id}
                                onClick={() => void importGmailMessage(message.id)}
                              >
                                {importingMessageId === message.id ? "Importing..." : "Import"}
                              </Button>
                            </ListItemButton>
                          </React.Fragment>
                        ))}
                      </List>
                    )}
                  </Paper>
                </>
              ) : null}
            </Box>
          )}
        </DialogContent>
        <DialogActions>
          <Button onClick={() => setImportOpen(false)}>Close</Button>
          {importTab === 0 ? (
            <Button variant="contained" onClick={importEmail}>
              Log Email
            </Button>
          ) : null}
        </DialogActions>
      </Dialog>
    </Box>
  );
}
