// ---------------------------------------------------------------------------
// Zustand demo store — in-memory CRUD for sandboxed demo experience
// No persist middleware: data resets on page reload.
// ---------------------------------------------------------------------------

import { create } from 'zustand';

import type { ResidenceResponse, MyResidenceResponse, TaskSummary } from '@/lib/api/residences';
import type { TaskResponse, CompletionResponse } from '@/lib/api/tasks';
import type { ContractorResponse } from '@/lib/api/contractors';
import type { DocumentResponse } from '@/lib/api/documents';
import type { NotificationResponse } from '@/lib/api/notifications';

import {
  demoResidences,
  demoMyResidences,
  demoTasks,
  demoCompletions,
  demoContractors,
  demoDocuments,
  demoNotifications,
} from './mock-data';

// ---------------------------------------------------------------------------
// State shape
// ---------------------------------------------------------------------------

interface DemoState {
  residences: ResidenceResponse[];
  myResidences: MyResidenceResponse[];
  tasks: TaskResponse[];
  completions: CompletionResponse[];
  contractors: ContractorResponse[];
  documents: DocumentResponse[];
  notifications: NotificationResponse[];

  nextIds: {
    residence: number;
    task: number;
    completion: number;
    contractor: number;
    document: number;
    notification: number;
  };

  // Residences
  addResidence: (data: Partial<ResidenceResponse>) => ResidenceResponse;
  updateResidence: (id: number, data: Partial<ResidenceResponse>) => ResidenceResponse;
  deleteResidence: (id: number) => void;

  // Tasks
  addTask: (data: Partial<TaskResponse>) => TaskResponse;
  updateTask: (id: number, data: Partial<TaskResponse>) => TaskResponse;
  deleteTask: (id: number) => void;
  markTaskInProgress: (id: number) => TaskResponse;
  cancelTask: (id: number) => TaskResponse;
  uncancelTask: (id: number) => TaskResponse;
  archiveTask: (id: number) => TaskResponse;
  unarchiveTask: (id: number) => TaskResponse;
  completeTask: (taskId: number, data: Partial<CompletionResponse>) => CompletionResponse;

  // Contractors
  addContractor: (data: Partial<ContractorResponse>) => ContractorResponse;
  updateContractor: (id: number, data: Partial<ContractorResponse>) => ContractorResponse;
  deleteContractor: (id: number) => void;
  toggleContractorFavorite: (id: number) => ContractorResponse;

  // Documents
  addDocument: (data: Partial<DocumentResponse>) => DocumentResponse;
  updateDocument: (id: number, data: Partial<DocumentResponse>) => DocumentResponse;
  deleteDocument: (id: number) => void;

  // Notifications
  markNotificationRead: (id: number) => void;
  markAllNotificationsRead: () => void;

  // Reset
  reset: () => void;
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

const now = () => new Date().toISOString();

function buildTaskSummary(tasks: TaskResponse[], residenceId: number): TaskSummary {
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  const dayMs = 86400000;

  const resTasks = tasks.filter(t => t.residence_id === residenceId && !t.is_cancelled && !t.is_archived);
  let overdue = 0, dueSoon = 0, inProgress = 0, completed = 0;

  for (const task of resTasks) {
    if (task.in_progress) { inProgress++; continue; }

    const isCompleted = task.completion_count > 0 && !task.next_due_date;
    const recentlyCompleted = task.last_completed_at && task.next_due_date &&
      new Date(task.next_due_date) > new Date(today.getTime() + 14 * dayMs);

    if (isCompleted || recentlyCompleted) { completed++; continue; }

    const dd = task.next_due_date || task.due_date;
    if (dd) {
      const dueDate = new Date(dd);
      dueDate.setHours(0, 0, 0, 0);
      const diff = Math.floor((dueDate.getTime() - today.getTime()) / dayMs);
      if (diff < 0) overdue++;
      else if (diff <= 7) dueSoon++;
    }
  }

  return { total: resTasks.length, overdue, due_soon: dueSoon, in_progress: inProgress, completed };
}

function rebuildMyResidences(residences: ResidenceResponse[], tasks: TaskResponse[]): MyResidenceResponse[] {
  return residences.map(residence => ({
    residence,
    task_summary: buildTaskSummary(tasks, residence.id),
  }));
}

// ---------------------------------------------------------------------------
// Initial state factory (for reset)
// ---------------------------------------------------------------------------

function initialState() {
  return {
    residences: structuredClone(demoResidences),
    myResidences: structuredClone(demoMyResidences),
    tasks: structuredClone(demoTasks),
    completions: structuredClone(demoCompletions),
    contractors: structuredClone(demoContractors),
    documents: structuredClone(demoDocuments),
    notifications: structuredClone(demoNotifications),
    nextIds: {
      residence: 100,
      task: 100,
      completion: 100,
      contractor: 100,
      document: 100,
      notification: 100,
    },
  };
}

// ---------------------------------------------------------------------------
// Store
// ---------------------------------------------------------------------------

export const useDemoStore = create<DemoState>()((set, get) => ({
  ...initialState(),

  // -------------------------------------------------------------------------
  // Residences
  // -------------------------------------------------------------------------

  addResidence: (data) => {
    const state = get();
    const id = state.nextIds.residence;
    const residence: ResidenceResponse = {
      id,
      name: data.name ?? 'New Residence',
      property_type_id: data.property_type_id,
      property_type: data.property_type,
      street_address: data.street_address ?? '',
      apartment_unit: data.apartment_unit ?? '',
      city: data.city ?? '',
      state_province: data.state_province ?? '',
      postal_code: data.postal_code ?? '',
      country: data.country ?? 'US',
      bedrooms: data.bedrooms,
      bathrooms: data.bathrooms,
      square_footage: data.square_footage,
      lot_size: data.lot_size,
      year_built: data.year_built,
      description: data.description ?? '',
      purchase_date: data.purchase_date,
      purchase_price: data.purchase_price,
      is_primary: data.is_primary ?? false,
      is_owner: true,
      owner_id: 1,
      user_count: 1,
      created_at: now(),
      updated_at: now(),
    };
    const newResidences = [...state.residences, residence];
    set({
      residences: newResidences,
      myResidences: rebuildMyResidences(newResidences, state.tasks),
      nextIds: { ...state.nextIds, residence: id + 1 },
    });
    return residence;
  },

  updateResidence: (id, data) => {
    const state = get();
    const newResidences = state.residences.map(r =>
      r.id === id ? { ...r, ...data, id, updated_at: now() } : r,
    );
    const updated = newResidences.find(r => r.id === id)!;
    set({
      residences: newResidences,
      myResidences: rebuildMyResidences(newResidences, state.tasks),
    });
    return updated;
  },

  deleteResidence: (id) => {
    const state = get();
    const newResidences = state.residences.filter(r => r.id !== id);
    const newTasks = state.tasks.filter(t => t.residence_id !== id);
    const newDocuments = state.documents.filter(d => d.residence_id !== id);
    set({
      residences: newResidences,
      tasks: newTasks,
      documents: newDocuments,
      myResidences: rebuildMyResidences(newResidences, newTasks),
    });
  },

  // -------------------------------------------------------------------------
  // Tasks
  // -------------------------------------------------------------------------

  addTask: (data) => {
    const state = get();
    const id = state.nextIds.task;
    const residence = state.residences.find(r => r.id === data.residence_id);
    const task: TaskResponse = {
      id,
      residence_id: data.residence_id ?? 1,
      residence_name: residence?.name ?? 'Unknown',
      title: data.title ?? 'New Task',
      description: data.description ?? '',
      category_id: data.category_id,
      category: data.category,
      priority_id: data.priority_id,
      priority: data.priority,
      frequency_id: data.frequency_id,
      in_progress: data.in_progress ?? false,
      is_cancelled: false,
      is_archived: false,
      due_date: data.due_date,
      next_due_date: data.due_date,
      estimated_cost: data.estimated_cost,
      contractor_id: data.contractor_id,
      contractor: data.contractor,
      completion_count: 0,
      created_by_id: 1,
      created_at: now(),
      updated_at: now(),
    };
    const newTasks = [...state.tasks, task];
    set({
      tasks: newTasks,
      myResidences: rebuildMyResidences(state.residences, newTasks),
      nextIds: { ...state.nextIds, task: id + 1 },
    });
    return task;
  },

  updateTask: (id, data) => {
    const state = get();
    const newTasks = state.tasks.map(t =>
      t.id === id ? { ...t, ...data, id, updated_at: now() } : t,
    );
    const updated = newTasks.find(t => t.id === id)!;
    set({
      tasks: newTasks,
      myResidences: rebuildMyResidences(state.residences, newTasks),
    });
    return updated;
  },

  deleteTask: (id) => {
    const state = get();
    const newTasks = state.tasks.filter(t => t.id !== id);
    set({
      tasks: newTasks,
      completions: state.completions.filter(c => c.task_id !== id),
      myResidences: rebuildMyResidences(state.residences, newTasks),
    });
  },

  markTaskInProgress: (id) => {
    return get().updateTask(id, { in_progress: true });
  },

  cancelTask: (id) => {
    return get().updateTask(id, { is_cancelled: true, in_progress: false });
  },

  uncancelTask: (id) => {
    return get().updateTask(id, { is_cancelled: false });
  },

  archiveTask: (id) => {
    return get().updateTask(id, { is_archived: true });
  },

  unarchiveTask: (id) => {
    return get().updateTask(id, { is_archived: false });
  },

  completeTask: (taskId, data) => {
    const state = get();
    const completionId = state.nextIds.completion;
    const task = state.tasks.find(t => t.id === taskId);

    const completion: CompletionResponse = {
      id: completionId,
      task_id: taskId,
      task_title: task?.title ?? '',
      completed_at: data.completed_at ?? now(),
      completed_by_id: 1,
      completed_by: { id: 1, username: 'demo_user', first_name: 'Demo', last_name: 'User' },
      notes: data.notes ?? '',
      actual_cost: data.actual_cost,
      rating: data.rating,
      images: data.images ?? [],
      created_at: now(),
    };

    // Update task: increment completion_count, set last_completed_at, advance next_due_date for recurring
    const taskUpdates: Partial<TaskResponse> = {
      completion_count: (task?.completion_count ?? 0) + 1,
      last_completed_at: completion.completed_at,
      in_progress: false,
      actual_cost: data.actual_cost,
    };

    // Advance next_due_date for recurring tasks
    if (task?.frequency_id) {
      const frequencyDays: Record<number, number> = { 1: 7, 2: 14, 3: 30, 4: 90, 5: 180, 6: 365 };
      const days = frequencyDays[task.frequency_id] ?? 30;
      const nextDate = new Date(Date.now() + days * 86400000);
      taskUpdates.next_due_date = nextDate.toISOString().split('T')[0];
    } else {
      // One-time task: clear next_due_date to mark as completed
      taskUpdates.next_due_date = undefined;
    }

    const newTasks = state.tasks.map(t =>
      t.id === taskId ? { ...t, ...taskUpdates, updated_at: now() } : t,
    );

    set({
      tasks: newTasks,
      completions: [...state.completions, completion],
      myResidences: rebuildMyResidences(state.residences, newTasks),
      nextIds: { ...state.nextIds, completion: completionId + 1 },
    });

    return completion;
  },

  // -------------------------------------------------------------------------
  // Contractors
  // -------------------------------------------------------------------------

  addContractor: (data) => {
    const state = get();
    const id = state.nextIds.contractor;
    const contractor: ContractorResponse = {
      id,
      name: data.name ?? 'New Contractor',
      company: data.company ?? '',
      phone: data.phone ?? '',
      email: data.email ?? '',
      website: data.website ?? '',
      notes: data.notes ?? '',
      street_address: data.street_address ?? '',
      city: data.city ?? '',
      state_province: data.state_province ?? '',
      postal_code: data.postal_code ?? '',
      specialties: data.specialties ?? [],
      rating: data.rating,
      is_favorite: data.is_favorite ?? false,
      task_count: 0,
      created_by_id: 1,
      created_at: now(),
      updated_at: now(),
    };
    set({
      contractors: [...state.contractors, contractor],
      nextIds: { ...state.nextIds, contractor: id + 1 },
    });
    return contractor;
  },

  updateContractor: (id, data) => {
    const state = get();
    const newContractors = state.contractors.map(c =>
      c.id === id ? { ...c, ...data, id, updated_at: now() } : c,
    );
    set({ contractors: newContractors });
    return newContractors.find(c => c.id === id)!;
  },

  deleteContractor: (id) => {
    set(state => ({ contractors: state.contractors.filter(c => c.id !== id) }));
  },

  toggleContractorFavorite: (id) => {
    const state = get();
    const contractor = state.contractors.find(c => c.id === id);
    if (!contractor) throw new Error(`Contractor ${id} not found`);
    return get().updateContractor(id, { is_favorite: !contractor.is_favorite });
  },

  // -------------------------------------------------------------------------
  // Documents
  // -------------------------------------------------------------------------

  addDocument: (data) => {
    const state = get();
    const id = state.nextIds.document;
    const residence = state.residences.find(r => r.id === data.residence_id);
    const document: DocumentResponse = {
      id,
      residence_id: data.residence_id ?? 1,
      residence_name: residence?.name ?? 'Unknown',
      title: data.title ?? 'New Document',
      description: data.description ?? '',
      document_type: data.document_type ?? 'general',
      file_url: data.file_url ?? '',
      file_name: data.file_name ?? '',
      file_size: data.file_size,
      mime_type: data.mime_type ?? 'application/pdf',
      purchase_date: data.purchase_date,
      expiry_date: data.expiry_date,
      purchase_price: data.purchase_price,
      vendor: data.vendor ?? '',
      serial_number: data.serial_number ?? '',
      model_number: data.model_number ?? '',
      is_active: data.is_active ?? true,
      images: data.images ?? [],
      created_by: data.created_by ?? { id: 1, username: 'demo_user', first_name: 'Demo', last_name: 'User' },
      created_at: now(),
      updated_at: now(),
    };
    set({
      documents: [...state.documents, document],
      nextIds: { ...state.nextIds, document: id + 1 },
    });
    return document;
  },

  updateDocument: (id, data) => {
    const state = get();
    const newDocuments = state.documents.map(d =>
      d.id === id ? { ...d, ...data, id, updated_at: now() } : d,
    );
    set({ documents: newDocuments });
    return newDocuments.find(d => d.id === id)!;
  },

  deleteDocument: (id) => {
    set(state => ({ documents: state.documents.filter(d => d.id !== id) }));
  },

  // -------------------------------------------------------------------------
  // Notifications
  // -------------------------------------------------------------------------

  markNotificationRead: (id) => {
    set(state => ({
      notifications: state.notifications.map(n =>
        n.id === id ? { ...n, is_read: true } : n,
      ),
    }));
  },

  markAllNotificationsRead: () => {
    set(state => ({
      notifications: state.notifications.map(n => ({ ...n, is_read: true })),
    }));
  },

  // -------------------------------------------------------------------------
  // Reset
  // -------------------------------------------------------------------------

  reset: () => {
    set(initialState());
  },
}));
