import { useState, useEffect, useCallback } from 'react';
import { useParams, useNavigate } from 'react-router';
import { useTranslation } from 'react-i18next';
import type { ApartmentWithRooms, Room, Point } from '@house-plan-maker/shared';
import {
  getApartment,
  getRooms,
  getRoomFull,
  createRoom,
  updateRoom,
  deleteRoom,
  cloneRoom,
} from '../api/client';
import {
  createApartmentPdf,
  downloadBlob,
  sanitizeFilename,
} from '../components/editor/export/exportUtils';
import { Button } from '../components/ui/Button';
import { LoadingSpinner } from '../components/ui/LoadingSpinner';
import { ErrorBanner } from '../components/ui/ErrorBanner';
import { EmptyState } from '../components/ui/EmptyState';
import { RoomCard } from '../components/rooms/RoomCard';
import { RoomFormModal } from '../components/rooms/RoomFormModal';
import { ConfirmDialog } from '../components/shared/ConfirmDialog';
import { TemplatePicker } from '../components/editor/templates/TemplatePicker';
import type { CreateRoomDto } from '@house-plan-maker/shared';
import styles from './apartment-detail-page.module.css';

export function ApartmentDetailPage() {
  const { t } = useTranslation();
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const [apartment, setApartment] = useState<ApartmentWithRooms | null>(null);
  const [rooms, setRooms] = useState<readonly Room[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  // Form modal state
  const [formOpen, setFormOpen] = useState(false);
  const [editingRoom, setEditingRoom] = useState<Room | null>(null);
  const [formLoading, setFormLoading] = useState(false);

  // Template picker state
  const [templatePickerOpen, setTemplatePickerOpen] = useState(false);

  // Delete dialog state
  const [deleteTarget, setDeleteTarget] = useState<Room | null>(null);
  const [deleteLoading, setDeleteLoading] = useState(false);

  // Per-room clone-in-flight set so individual buttons can show a spinner
  // without blocking the rest of the page.
  const [cloningIds, setCloningIds] = useState<ReadonlySet<string>>(new Set());

  // PDF export state
  const [exportLoading, setExportLoading] = useState(false);

  const fetchData = useCallback(async () => {
    if (!id) return;
    try {
      setError(null);
      const [apt, roomList] = await Promise.all([
        getApartment(id),
        getRooms(id),
      ]);
      setApartment(apt);
      setRooms(roomList);
    } catch (err: unknown) {
      const message = err instanceof Error ? err.message : t('rooms.error.load');
      setError(message);
    } finally {
      setLoading(false);
    }
  }, [id, t]);

  useEffect(() => {
    fetchData();
  }, [fetchData]);

  const handleCreateRoom = () => {
    setEditingRoom(null);
    setFormOpen(true);
  };

  const handleEditRoom = (room: Room) => {
    setEditingRoom(room);
    setFormOpen(true);
  };

  const handleRoomFormSubmit = async (data: {
    name: string;
    shape: readonly Point[];
    width: number | null;
    height: number | null;
    wallHeight: number;
    plinthHeight: number;
    plinthThickness: number;
  }) => {
    if (!id) return;
    setFormLoading(true);
    try {
      const payload = {
        name: data.name,
        shape: data.shape.length > 0 ? [...data.shape] : undefined,
        width: data.width,
        height: data.height,
        wallHeight: data.wallHeight,
        plinthHeight: data.plinthHeight,
        plinthThickness: data.plinthThickness,
      };

      if (editingRoom) {
        await updateRoom(editingRoom.id, payload);
      } else {
        await createRoom(id, payload);
      }

      setFormOpen(false);
      await fetchData();
    } catch (err: unknown) {
      const message = err instanceof Error ? err.message : t('rooms.error.operation');
      setError(message);
    } finally {
      setFormLoading(false);
    }
  };

  const handleCreateFromTemplate = async (dto: CreateRoomDto) => {
    if (!id) return;
    setFormLoading(true);
    try {
      await createRoom(id, {
        name: dto.name,
        shape: dto.shape ? [...dto.shape] : undefined,
        width: dto.width,
        height: dto.height,
        wallHeight: dto.wallHeight,
        order: dto.order,
      });
      await fetchData();
    } catch (err: unknown) {
      const message = err instanceof Error ? err.message : t('rooms.error.create');
      setError(message);
    } finally {
      setFormLoading(false);
    }
  };

  const handleDeleteClick = (room: Room) => {
    setDeleteTarget(room);
  };

  const handleCloneRoom = useCallback(
    async (room: Room) => {
      setCloningIds((prev) => {
        const next = new Set(prev);
        next.add(room.id);
        return next;
      });
      try {
        await cloneRoom(room.id);
        await fetchData();
      } catch (err: unknown) {
        const message = err instanceof Error ? err.message : t('rooms.error.operation');
        setError(message);
      } finally {
        setCloningIds((prev) => {
          const next = new Set(prev);
          next.delete(room.id);
          return next;
        });
      }
    },
    [fetchData, t],
  );

  const handleDeleteConfirm = async () => {
    if (!deleteTarget) return;
    setDeleteLoading(true);
    try {
      await deleteRoom(deleteTarget.id);
      setDeleteTarget(null);
      await fetchData();
    } catch (err: unknown) {
      const message = err instanceof Error ? err.message : t('rooms.error.delete');
      setError(message);
    } finally {
      setDeleteLoading(false);
    }
  };

  const handleExportPdf = useCallback(async () => {
    if (!apartment || rooms.length === 0) return;
    setExportLoading(true);
    try {
      const fullRooms = await Promise.all(
        rooms.map((room) => getRoomFull(room.id)),
      );

      const pdfRooms = fullRooms.map((room) => ({
        roomName: room.name,
        topDownDataUrl: null as string | null,
        projectionDataUrls: [] as readonly { readonly label: string; readonly dataUrl: string }[],
      }));

      const pdf = await createApartmentPdf(apartment.name, pdfRooms);
      const blob = pdf.output('blob');
      const filename = `${sanitizeFilename(apartment.name)}_apartment.pdf`;
      downloadBlob(blob, filename);
    } catch (err: unknown) {
      const message = err instanceof Error ? err.message : 'Failed to export PDF';
      setError(message);
    } finally {
      setExportLoading(false);
    }
  }, [apartment, rooms]);

  if (loading) {
    return <LoadingSpinner />;
  }

  if (!apartment || !id) {
    return (
      <ErrorBanner message={error ?? t('apartment.notFound')} />
    );
  }

  return (
    <div className={styles.page}>
      <div className={styles.header}>
        <div className={styles.headerInfo}>
          <h1 className={styles.title}>{apartment.name}</h1>
          {apartment.address && (
            <p className={styles.subtitle}>{apartment.address}</p>
          )}
          <div className={styles.meta}>
            {apartment.totalArea != null && (
              <span className={styles.metaBadge}>
                {apartment.totalArea} m&sup2;
              </span>
            )}
            <span className={styles.metaBadge}>
              {t('rooms.count', { count: rooms.length })}
            </span>
          </div>
        </div>
        <div style={{ display: 'flex', gap: '8px' }}>
          {rooms.length > 0 && (
            <Button
              variant="secondary"
              onClick={handleExportPdf}
              disabled={exportLoading}
            >
              {exportLoading ? 'Exporting...' : 'Export PDF'}
            </Button>
          )}
          {rooms.length > 0 && (
            <Button
              variant="secondary"
              onClick={() => navigate(`/apartments/${id}/floorplan`)}
            >
              {t('breadcrumb.floorPlan')}
            </Button>
          )}
        </div>
      </div>

      {error && <ErrorBanner message={error} onDismiss={() => setError(null)} />}

      <div className={styles.sectionHeader}>
        <h2 className={styles.sectionTitle}>{t('rooms.title')}</h2>
        <div style={{ display: 'flex', gap: '8px' }}>
          <Button onClick={() => setTemplatePickerOpen(true)} size="sm" variant="secondary">
            {t('rooms.fromTemplate')}
          </Button>
          <Button onClick={handleCreateRoom} size="sm">
            {t('rooms.add')}
          </Button>
        </div>
      </div>

      {rooms.length === 0 && !error ? (
        <EmptyState
          title={t('rooms.empty.title')}
          description={t('rooms.empty.description')}
          action={
            <Button onClick={handleCreateRoom}>{t('rooms.addFirst')}</Button>
          }
        />
      ) : (
        <div className={styles.roomList}>
          {rooms.map((room) => (
            <RoomCard
              key={room.id}
              room={room}
              apartmentId={id}
              onEdit={handleEditRoom}
              onDelete={handleDeleteClick}
              onClone={handleCloneRoom}
              cloneLoading={cloningIds.has(room.id)}
            />
          ))}
        </div>
      )}

      <RoomFormModal
        open={formOpen}
        onClose={() => setFormOpen(false)}
        onSubmit={handleRoomFormSubmit}
        room={editingRoom}
        loading={formLoading}
      />

      <ConfirmDialog
        open={deleteTarget != null}
        onClose={() => setDeleteTarget(null)}
        onConfirm={handleDeleteConfirm}
        title={t('rooms.delete.title')}
        message={t('rooms.delete.message', { name: deleteTarget?.name ?? '' })}
        loading={deleteLoading}
      />

      <TemplatePicker
        open={templatePickerOpen}
        onClose={() => setTemplatePickerOpen(false)}
        onCreateRoom={handleCreateFromTemplate}
        roomCount={rooms.length}
      />
    </div>
  );
}
