/**
 * Calendar plugin API client.
 *
 * All requests use the shared `apiClient` (`baseURL: '/api/v1'`) and target the
 * Calendar plugin routes under `/calendar/...`, `/calendars/...` and
 * `/resources/...`.
 */

import { apiClient, apiDelete, apiGet, apiPatch, apiPost } from './client';

// ─── Types ─────────────────────────────────────────────────────────────────

export type EntryType = 'appointment' | 'task';
export type EntryStatus = 'open' | 'in_progress' | 'done' | 'cancelled';
export type EntrySubtype = 'normal' | 'follow_up' | 'private';
export type EntryPriority = 'low' | 'medium' | 'high';
export type CalendarType = 'personal' | 'team' | 'project' | 'company';
export type SharePermission = 'read' | 'write';

export interface Subtask {
  id: string;
  entry_id: string;
  title: string;
  done: boolean;
  created_at?: string | null;
  updated_at?: string | null;
}

export interface CalendarEntry {
  id: string;
  calendar_id: string;
  entry_type: EntryType;
  subtype: EntrySubtype;
  title: string;
  description?: string | null;
  start_at?: string | null;
  end_at?: string | null;
  all_day: boolean;
  location?: string | null;
  due_date?: string | null;
  priority: EntryPriority;
  status: EntryStatus;
  assigned_to?: string | null;
  reminder?: Record<string, unknown> | null;
  recurrence?: Record<string, unknown> | null;
  created_by: string;
  created_at?: string | null;
  updated_at?: string | null;
  links?: CalendarEntryLink[];
  subtasks?: Subtask[];
  occurrence_date?: string | null;
}

export interface CalendarEntryLink {
  id: string;
  entity_type: 'contact' | 'company';
  entity_id: string;
}

export interface Calendar {
  id: string;
  name: string;
  color: string;
  type: CalendarType;
  owner_id: string;
  ics_token?: string | null;
  created_at?: string | null;
  updated_at?: string | null;
}

export interface CalendarShare {
  id: string;
  calendar_id: string;
  user_id?: string | null;
  group_id?: string | null;
  permission: SharePermission;
}

export interface Resource {
  id: string;
  name: string;
  type: string;
}

export interface ResourceBooking {
  id: string;
  resource_id: string;
  entry_id: string;
  start_at: string;
  end_at: string;
}

export interface KanbanBoard {
  open: CalendarEntry[];
  in_progress: CalendarEntry[];
  done: CalendarEntry[];
  cancelled: CalendarEntry[];
}

// ─── Payloads ──────────────────────────────────────────────────────────────

export interface CalendarCreatePayload {
  name: string;
  color?: string;
  type?: CalendarType;
}

export interface EntryCreatePayload {
  calendar_id: string;
  entry_type: EntryType;
  title: string;
  subtype?: EntrySubtype;
  description?: string | null;
  start_at?: string | null;
  end_at?: string | null;
  all_day?: boolean;
  location?: string | null;
  due_date?: string | null;
  priority?: EntryPriority;
  status?: EntryStatus;
  assigned_to?: string | null;
  reminder?: Record<string, unknown> | null;
  recurrence?: Record<string, unknown> | null;
}

export interface EntryUpdatePayload {
  calendar_id?: string;
  subtype?: EntrySubtype;
  title?: string;
  description?: string | null;
  start_at?: string | null;
  end_at?: string | null;
  all_day?: boolean;
  location?: string | null;
  due_date?: string | null;
  priority?: EntryPriority;
  status?: EntryStatus;
  assigned_to?: string | null;
  reminder?: Record<string, unknown> | null;
  recurrence?: Record<string, unknown> | null;
}

export interface SubtaskCreatePayload {
  title: string;
}

export interface SubtaskUpdatePayload {
  title?: string;
  done?: boolean;
}

export interface SharePayload {
  user_id?: string;
  group_id?: string;
  permission: SharePermission;
}

export interface ResourceCreatePayload {
  name: string;
  type: string;
}

export interface BookResourcePayload {
  resource_id: string;
}

// ─── Calendars ─────────────────────────────────────────────────────────────

export function fetchCalendars(): Promise<Calendar[]> {
  return apiGet<Calendar[]>('/calendars');
}

export function createCalendar(payload: CalendarCreatePayload): Promise<Calendar> {
  return apiPost<Calendar>('/calendars', payload);
}

export function updateCalendar(
  calendarId: string,
  payload: Partial<CalendarCreatePayload>
): Promise<Calendar> {
  return apiPatch<Calendar>(`/calendars/${calendarId}`, payload);
}

export function deleteCalendar(calendarId: string): Promise<void> {
  return apiDelete<void>(`/calendars/${calendarId}`);
}

// ─── Shares ────────────────────────────────────────────────────────────────

export function shareCalendar(calendarId: string, payload: SharePayload): Promise<CalendarShare> {
  return apiPost<CalendarShare>(`/calendars/${calendarId}/share`, payload);
}

export function fetchCalendarPermissions(calendarId: string): Promise<CalendarShare[]> {
  return apiGet<CalendarShare[]>(`/calendars/${calendarId}/permissions`);
}

// ─── Entries ───────────────────────────────────────────────────────────────

export interface ListEntriesParams {
  start?: string;
  end?: string;
}

export function listEntries(params: ListEntriesParams = {}): Promise<CalendarEntry[]> {
  const search: Record<string, string> = {};
  if (params.start) search.start = params.start;
  if (params.end) search.end = params.end;
  const qs = new URLSearchParams(search).toString();
  return apiGet<CalendarEntry[]>(`/calendar/entries${qs ? `?${qs}` : ''}`);
}

export function createEntry(payload: EntryCreatePayload): Promise<CalendarEntry> {
  return apiPost<CalendarEntry>('/calendar/entries', payload);
}

export function getEntry(entryId: string): Promise<CalendarEntry> {
  return apiGet<CalendarEntry>(`/calendar/entries/${entryId}`);
}

export function updateEntry(
  entryId: string,
  payload: EntryUpdatePayload
): Promise<CalendarEntry> {
  return apiPatch<CalendarEntry>(`/calendar/entries/${entryId}`, payload);
}

export function deleteEntry(entryId: string): Promise<void> {
  return apiDelete<void>(`/calendar/entries/${entryId}`);
}

// ─── Subtasks ──────────────────────────────────────────────────────────────

export function createSubtask(
  entryId: string,
  payload: SubtaskCreatePayload
): Promise<Subtask> {
  return apiPost<Subtask>(`/calendar/entries/${entryId}/subtasks`, payload);
}

export function updateSubtask(
  entryId: string,
  subId: string,
  payload: SubtaskUpdatePayload
): Promise<Subtask> {
  return apiPatch<Subtask>(
    `/calendar/entries/${entryId}/subtasks/${subId}`,
    payload
  );
}

// ─── Kanban ────────────────────────────────────────────────────────────────

export function fetchKanbanBoard(): Promise<KanbanBoard> {
  return apiGet<KanbanBoard>('/calendar/kanban');
}

// ─── ICS Feed / Import ─────────────────────────────────────────────────────

export function getIcsFeedUrl(calendarId: string, token?: string | null): string {
  const base = `/calendar/${calendarId}/ics-feed`;
  if (!token) return base;
  return `${base}?token=${encodeURIComponent(token)}`;
}

/** Fetch ICS file as text (used by "Download .ics" button). */
export async function downloadIcsFile(calendarId: string, calendarName: string): Promise<void> {
  const response = await apiClient.get(`/calendar/${calendarId}/ics-feed-public`, {
    responseType: 'text',
    transformResponse: [(d) => d],
  });
  const blob = new Blob([response.data as BlobPart], { type: 'text/calendar' });
  const url = window.URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  const safeName = calendarName.replace(/[^a-zA-Z0-9_-]+/g, '_');
  a.download = `${safeName || 'calendar'}.ics`;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  window.URL.revokeObjectURL(url);
}

export interface ImportIcsResult {
  entries_created: number;
  errors: string[];
}

export function importIcsFile(
  file: File,
  calendarId?: string
): Promise<ImportIcsResult> {
  const form = new FormData();
  form.append('file', file);
  const url = calendarId ? `/calendar/import?calendar_id=${calendarId}` : '/calendar/import';
  return apiPost<ImportIcsResult>(url, form, {
    headers: { 'Content-Type': 'multipart/form-data' },
  });
}

// ─── Resources ─────────────────────────────────────────────────────────────

export function createResource(payload: ResourceCreatePayload): Promise<Resource> {
  return apiPost<Resource>('/resources', payload);
}

export function bookResource(
  entryId: string,
  payload: BookResourcePayload
): Promise<ResourceBooking> {
  return apiPost<ResourceBooking>(`/calendar/entries/${entryId}/book-resource`, payload);
}
