import {
  Box,
  Center,
  Group,
  Loader,
  Paper,
  Popover,
  Select,
  SimpleGrid,
  Stack,
  Text,
  Title,
  UnstyledButton,
} from "@mantine/core";
import { MonthPickerInput } from "@mantine/dates";
import { IconCheckbox, IconHourglass, IconPlus } from "@tabler/icons-react";
import dayjs from "dayjs";
import { useEffect, useMemo, useState } from "react";
import * as api from "../api";
import type { Card, Metrics, User } from "../types";

// Hace clickable el numero del dia para abrir el reporte diario (issue 0093).
interface Props {
  users: User[];
  cards: Card[];
  onJumpToCard?: (cardId: string) => void;
  onOpenDailyReport?: (date: string) => void;
}

const DAY_LABELS = ["Lun", "Mar", "Mie", "Jue", "Vie", "Sab", "Dom"];

export function CalendarView({ users, cards, onJumpToCard, onOpenDailyReport }: Props) {
  const [openDate, setOpenDate] = useState<string | null>(null);
  const [month, setMonth] = useState<Date>(new Date());
  const [assigneeId, setAssigneeId] = useState<string | null>(null);
  const [data, setData] = useState<Metrics | null>(null);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    const start = dayjs(month).startOf("month").format("YYYY-MM-DD");
    const end = dayjs(month).endOf("month").format("YYYY-MM-DD");
    api
      .getMetrics({ from: start, to: end, assignee_id: assigneeId || undefined })
      .then((m) => {
        if (!cancelled) setData(m);
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [month, assigneeId]);

  const userOptions = useMemo(
    () => users.map((u) => ({ value: u.id, label: u.display_name || u.username })),
    [users]
  );

  const dayMap = useMemo(() => {
    const m = new Map<string, { created: number; done: number; deadlines: Card[] }>();
    if (!data) return m;
    for (const d of data.created_daily) {
      const cur = m.get(d.date) ?? { created: 0, done: 0, deadlines: [] };
      cur.created = d.count;
      m.set(d.date, cur);
    }
    for (const d of data.throughput_daily) {
      const cur = m.get(d.date) ?? { created: 0, done: 0, deadlines: [] };
      cur.done = d.count;
      m.set(d.date, cur);
    }
    for (const c of cards) {
      if (!c.deadline || c.deleted_at) continue;
      const date = c.deadline.slice(0, 10);
      const cur = m.get(date) ?? { created: 0, done: 0, deadlines: [] };
      cur.deadlines.push(c);
      m.set(date, cur);
    }
    return m;
  }, [data, cards]);

  // Build month grid (Mon-first).
  const grid = useMemo(() => {
    const start = dayjs(month).startOf("month");
    const end = dayjs(month).endOf("month");
    // Day-of-week, ISO Mon=1..Sun=7. We want first cell to be Mon.
    const firstDow = (start.day() + 6) % 7; // 0=Mon
    const cells: { date: string | null; inMonth: boolean }[] = [];
    for (let i = 0; i < firstDow; i++) cells.push({ date: null, inMonth: false });
    for (let d = start; !d.isAfter(end); d = d.add(1, "day")) {
      cells.push({ date: d.format("YYYY-MM-DD"), inMonth: true });
    }
    while (cells.length % 7 !== 0) cells.push({ date: null, inMonth: false });
    return cells;
  }, [month]);

  const totalCreated = useMemo(
    () => Array.from(dayMap.values()).reduce((s, v) => s + v.created, 0),
    [dayMap]
  );
  const totalDone = useMemo(
    () => Array.from(dayMap.values()).reduce((s, v) => s + v.done, 0),
    [dayMap]
  );

  return (
    <Box p="md">
      <Stack gap="md">
        <Group justify="space-between">
          <Title order={3}>Calendario</Title>
          <Group gap="xs" wrap="nowrap">
            <MonthPickerInput
              label="Mes"
              size="xs"
              value={month}
              onChange={(v) => v && setMonth(typeof v === "string" ? new Date(v) : v)}
              style={{ minWidth: 160 }}
              clearable={false}
            />
            <Select
              label="Asignado"
              size="xs"
              placeholder="Todos"
              value={assigneeId}
              onChange={setAssigneeId}
              data={userOptions}
              clearable
              searchable
              style={{ minWidth: 180 }}
            />
          </Group>
        </Group>

        <Group gap="md">
          <Paper withBorder p="sm" radius="md">
            <Group gap={6}>
              <IconPlus size={14} color="var(--mantine-color-blue-5)" />
              <Text size="sm" fw={600}>
                {totalCreated}
              </Text>
              <Text size="xs" c="dimmed">
                creadas
              </Text>
            </Group>
          </Paper>
          <Paper withBorder p="sm" radius="md">
            <Group gap={6}>
              <IconCheckbox size={14} color="var(--mantine-color-green-5)" />
              <Text size="sm" fw={600}>
                {totalDone}
              </Text>
              <Text size="xs" c="dimmed">
                hechas
              </Text>
            </Group>
          </Paper>
        </Group>

        {loading && !data ? (
          <Center p="xl">
            <Loader />
          </Center>
        ) : (
          <Paper withBorder p="md" radius="md">
            <SimpleGrid cols={7} spacing={4} mb={4}>
              {DAY_LABELS.map((d) => (
                <Text key={d} size="xs" c="dimmed" ta="center" fw={600}>
                  {d}
                </Text>
              ))}
            </SimpleGrid>
            <SimpleGrid cols={7} spacing={4}>
              {grid.map((cell, i) => {
                if (!cell.date) {
                  return <Box key={i} style={{ minHeight: 72 }} />;
                }
                const stats = dayMap.get(cell.date) ?? { created: 0, done: 0, deadlines: [] as Card[] };
                const dayNum = parseInt(cell.date.slice(8, 10), 10);
                const isToday = cell.date === dayjs().format("YYYY-MM-DD");
                const todayMs = dayjs().startOf("day").valueOf();
                const cellMs = dayjs(cell.date).startOf("day").valueOf();
                const overdueDay = cellMs < todayMs;
                return (
                  <Paper
                    key={i}
                    p={6}
                    withBorder
                    radius="sm"
                    style={{
                      minHeight: 72,
                      borderColor: isToday ? "var(--mantine-color-blue-5)" : undefined,
                      background:
                        stats.done > 0
                          ? "rgba(81, 207, 102, 0.08)"
                          : stats.created > 0
                          ? "rgba(34, 139, 230, 0.06)"
                          : undefined,
                    }}
                  >
                    <Stack gap={2}>
                      <UnstyledButton
                        onClick={() => cell.date && onOpenDailyReport?.(cell.date as string)}
                        title="Ver reporte diario"
                        style={{ alignSelf: "flex-start" }}
                        data-test={`calendar-day-${cell.date}`}
                      >
                        <Text
                          size="xs"
                          fw={isToday ? 700 : 500}
                          c={isToday ? "blue" : undefined}
                          td={onOpenDailyReport ? "underline" : undefined}
                          style={{ cursor: onOpenDailyReport ? "pointer" : "default" }}
                        >
                          {dayNum}
                        </Text>
                      </UnstyledButton>
                      {stats.created > 0 && (
                        <Group gap={3} wrap="nowrap">
                          <IconPlus size={10} color="var(--mantine-color-blue-5)" />
                          <Text size="xs" c="blue">
                            {stats.created}
                          </Text>
                        </Group>
                      )}
                      {stats.done > 0 && (
                        <Group gap={3} wrap="nowrap">
                          <IconCheckbox size={10} color="var(--mantine-color-green-5)" />
                          <Text size="xs" c="green">
                            {stats.done}
                          </Text>
                        </Group>
                      )}
                      {stats.deadlines.length > 0 && (
                        <Popover
                          opened={openDate === cell.date}
                          onChange={(o) => setOpenDate(o ? cell.date : null)}
                          position="bottom"
                          withArrow
                          shadow="md"
                          width={280}
                        >
                          <Popover.Target>
                            <UnstyledButton
                              onClick={() => setOpenDate(openDate === cell.date ? null : cell.date)}
                              style={{ textAlign: "left" }}
                            >
                              <Stack gap={1}>
                                <Group gap={3} wrap="nowrap">
                                  <IconHourglass size={10} color={overdueDay ? "var(--mantine-color-red-5)" : "var(--mantine-color-orange-5)"} />
                                  <Text size="xs" c={overdueDay ? "red" : "orange"} fw={700} td="underline">
                                    {stats.deadlines.length} deadline{stats.deadlines.length === 1 ? "" : "s"}
                                  </Text>
                                </Group>
                              </Stack>
                            </UnstyledButton>
                          </Popover.Target>
                          <Popover.Dropdown p={6}>
                            <Stack gap={2}>
                              <Text size="xs" c="dimmed" fw={600} mb={2}>
                                Vencen el {dayjs(cell.date).format("DD/MM/YYYY")}
                              </Text>
                              {stats.deadlines.map((c) => (
                                <UnstyledButton
                                  key={c.id}
                                  onClick={() => {
                                    setOpenDate(null);
                                    onJumpToCard?.(c.id);
                                  }}
                                  style={{
                                    padding: "4px 6px",
                                    borderRadius: 4,
                                    background: "var(--mantine-color-dark-6)",
                                  }}
                                >
                                  <Group gap={6} wrap="nowrap">
                                    <Text size="xs" c="dimmed" ff="monospace">
                                      #{String(c.seq_num).padStart(5, "0")}
                                    </Text>
                                    <Text size="xs" lineClamp={1} title={c.title}>
                                      {c.title}
                                    </Text>
                                  </Group>
                                </UnstyledButton>
                              ))}
                            </Stack>
                          </Popover.Dropdown>
                        </Popover>
                      )}
                    </Stack>
                  </Paper>
                );
              })}
            </SimpleGrid>
          </Paper>
        )}
      </Stack>
    </Box>
  );
}
