import { useEffect, useMemo, useState } from "react";
import {
  AppShell,
  Badge,
  Box,
  Burger,
  Button,
  Center,
  Group,
  Loader,
  Stack,
  Text,
  Title,
} from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { notifications } from "@mantine/notifications";
import {
  IconLock,
  IconLogout,
  IconUserCircle,
} from "@tabler/icons-react";
import {
  Logout,
  SendMarkdown,
  SendText,
  Start,
  Stop,
} from "../wailsjs/go/main/MatrixService";
import { EventsOn } from "../wailsjs/runtime/runtime";
import RoomList from "./components/RoomList";
import Timeline from "./components/Timeline";
import Composer from "./components/Composer";
import { useMatrixRooms } from "./hooks/useMatrixRooms";
import { useMatrixTimeline } from "./hooks/useMatrixTimeline";

const NAVBAR_WIDTH = 300;

export default function HomeScreen({
  userID,
  onLogout,
}: {
  userID: string;
  onLogout: () => void;
}) {
  const [navOpen, navHandlers] = useDisclosure(true);
  const [activeRoomID, setActiveRoomID] = useState<string | null>(null);
  const [started, setStarted] = useState(false);
  const [startError, setStartError] = useState<string | null>(null);

  const { rooms } = useMatrixRooms(started);
  const { events, loading: timelineLoading, error: timelineError } = useMatrixTimeline(
    activeRoomID,
    50,
  );

  // Boot sync on mount; tear down on unmount.
  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        await Start(userID);
        if (!cancelled) setStarted(true);
      } catch (e: any) {
        if (!cancelled) {
          const msg = String(e?.message ?? e);
          setStartError(msg);
          notifications.show({
            title: "Sync error",
            message: msg,
            color: "red",
            autoClose: false,
          });
        }
      }
    })();
    return () => {
      cancelled = true;
      Stop().catch(() => {});
    };
  }, [userID]);

  // Show transient Matrix errors as toast notifications.
  useEffect(() => {
    const off = EventsOn("matrix:error", (msg: string) => {
      notifications.show({
        title: "Matrix",
        message: String(msg),
        color: "orange",
        autoClose: 6000,
      });
    });
    return () => {
      if (typeof off === "function") off();
    };
  }, []);

  const activeRoom = useMemo(
    () => rooms.find((r) => r.room_id === activeRoomID) || null,
    [rooms, activeRoomID],
  );

  async function handleLogout() {
    try {
      await Logout(userID);
    } finally {
      onLogout();
    }
  }

  async function handleSendText(body: string) {
    if (!activeRoomID) return;
    await SendText(activeRoomID, body);
  }

  async function handleSendMarkdown(md: string) {
    if (!activeRoomID) return;
    await SendMarkdown(activeRoomID, md);
  }

  return (
    <AppShell
      header={{ height: 56 }}
      navbar={{
        width: NAVBAR_WIDTH,
        breakpoint: 0,
        collapsed: { mobile: !navOpen, desktop: !navOpen },
      }}
      padding={0}
    >
      <AppShell.Header>
        <Group h="100%" px="md" justify="space-between" wrap="nowrap">
          <Group gap="xs" wrap="nowrap">
            <Burger
              opened={navOpen}
              onClick={navHandlers.toggle}
              size="sm"
              aria-label="Toggle rooms"
            />
            <IconUserCircle size={22} />
            <Text fw={600}>matrix_client_pc</Text>
            <Badge size="sm" variant="light" color="violet">
              v0.2.0
            </Badge>
            <Text size="xs" c="dimmed" visibleFrom="sm">
              {userID}
            </Text>
          </Group>
          <Button
            variant="subtle"
            color="gray"
            leftSection={<IconLogout size={16} />}
            onClick={handleLogout}
          >
            Logout
          </Button>
        </Group>
      </AppShell.Header>

      <AppShell.Navbar>
        <RoomList
          rooms={rooms}
          activeRoomID={activeRoomID}
          onSelect={setActiveRoomID}
        />
      </AppShell.Navbar>

      <AppShell.Main
        style={{
          display: "flex",
          flexDirection: "column",
          height: "calc(100vh - 56px)",
        }}
      >
        {!started && !startError && (
          <Center style={{ flex: 1 }}>
            <Stack align="center" gap="xs">
              <Loader />
              <Text size="sm" c="dimmed">
                Starting sync and crypto (up to 60s on first run)...
              </Text>
            </Stack>
          </Center>
        )}

        {startError && (
          <Center style={{ flex: 1 }}>
            <Stack align="center" gap="xs" maw={520} ta="center">
              <Title order={4} c="red">
                Could not start sync
              </Title>
              <Text size="sm" c="dimmed">
                {startError}
              </Text>
            </Stack>
          </Center>
        )}

        {started && !activeRoom && (
          <Center style={{ flex: 1 }}>
            <Text size="sm" c="dimmed">
              Pick a room from the sidebar to view messages
            </Text>
          </Center>
        )}

        {started && activeRoom && (
          <>
            <Box p="md" bg="dark.7" style={{ borderBottom: "1px solid var(--mantine-color-dark-5)" }}>
              <Group gap="xs">
                <Title order={5}>{activeRoom.name || activeRoom.room_id}</Title>
                {activeRoom.is_encrypted && (
                  <Badge size="xs" color="green" variant="light" leftSection={<IconLock size={10} />}>
                    E2EE
                  </Badge>
                )}
                <Text size="xs" c="dimmed">
                  {activeRoom.member_count} member{activeRoom.member_count === 1 ? "" : "s"}
                </Text>
              </Group>
              {activeRoom.topic && (
                <Text size="xs" c="dimmed" mt={4} lineClamp={1}>
                  {activeRoom.topic}
                </Text>
              )}
            </Box>

            <Box style={{ flex: 1, minHeight: 0 }}>
              <Timeline
                events={events}
                loading={timelineLoading}
                error={timelineError}
                selfUserID={userID}
              />
            </Box>

            <Composer
              disabled={!activeRoomID}
              onSendText={handleSendText}
              onSendMarkdown={handleSendMarkdown}
            />
          </>
        )}
      </AppShell.Main>
    </AppShell>
  );
}
