/**
 * Tipos del contrato de la API (fuente de verdad: docs/openapi.yaml).
 * Las entidades del bundle se tipan de forma laxa (campos opcionales) porque
 * el backend puede añadir columnas; sólo fijamos lo que la app consume.
 */

// ----- Auth -----

export interface User {
  id: number;
  name: string;
  email: string;
  roles: string[];
  permissions: string[];
}

export interface LoginRequest {
  email: string;
  password: string;
  device_name: string;
  app_version?: string;
}

export interface LoginResponse {
  token: string;
  user: User;
}

// ----- Entidades del bundle (PULL) -----

export interface Project {
  id: number;
  reference?: string;
  name: string;
  address?: string | null;
  lat?: number | null;
  lng?: number | null;
  status?: string;
  updated_at: string;
}

export interface Phase {
  id: number;
  name: string;
  order?: number;
  color?: string | null;
  progress_percent?: number;
  updated_at: string;
}

export interface Layer {
  id: number;
  phase_id: number;
  name: string;
  color?: string | null;
  updated_at: string;
}

export interface Feature {
  id: number;
  layer_id: number;
  name: string;
  geometry?: unknown; // GeoJSON
  status?: string;
  progress?: number;
  responsible?: string | null;
  template_id?: number | null;
  updated_at: string;
}

export interface Inspection {
  id: number;
  feature_id: number;
  layer_id?: number;
  template_id?: number | null;
  user_id?: number;
  data?: Record<string, unknown>;
  status?: string;
  result?: string | null;
  notes?: string | null;
  created_at?: string;
  updated_at: string;
}

export type IssuePriority = 'low' | 'medium' | 'high' | 'critical';
export type IssueStatus = 'open' | 'in_review' | 'resolved' | 'closed';
export type IssueType = 'defect' | 'safety' | 'quality' | 'documentation' | 'other';

export interface Issue {
  id: number;
  feature_id?: number | null;
  title: string;
  description?: string | null;
  status?: IssueStatus;
  priority?: IssuePriority;
  type?: IssueType;
  reported_by?: number;
  assigned_to?: number | null;
  resolved_at?: string | null;
  updated_at: string;
}

export interface IssueTask {
  id: number;
  issue_id: number;
  title: string;
  is_done?: boolean;
  done_at?: string | null;
  done_by?: number | null;
  assigned_to?: number | null;
  due_date?: string | null;
  order?: number;
  updated_at: string;
}

export interface IssueComment {
  id: number;
  issue_id: number;
  user_id?: number;
  body: string;
  created_at?: string;
  updated_at: string;
}

export interface Template {
  id: number;
  project_id?: number;
  phase_id?: number | null;
  name: string;
  description?: string | null;
  fields?: unknown[];
  version: number | string;
  hash?: string;
  updated_at: string;
}

export type MediaParentEntity =
  | 'feature'
  | 'issue'
  | 'issue_task'
  | 'issue_comment'
  | 'project'
  | 'phase'
  | 'layer';

export interface Media {
  id: number;
  uuid: string;
  parent_entity: MediaParentEntity;
  parent_id: number;
  url: string;
  name?: string;
  file_type?: string;
  category?: 'image' | 'document' | 'other';
  updated_at: string;
}

/** Tombstones: ids borrados por entidad (sólo en respuestas delta). */
export interface DeletedTombstones {
  phases?: number[];
  layers?: number[];
  features?: number[];
  inspections?: number[];
  issues?: number[];
  issue_tasks?: number[];
  issue_comments?: number[];
}

export interface Bundle {
  server_time: string;
  project: Project;
  phases: Phase[];
  layers: Layer[];
  features: Feature[];
  inspections: Inspection[];
  issues: Issue[];
  issue_tasks: IssueComment[] | IssueTask[];
  issue_comments: IssueComment[];
  templates: Template[];
  media: Media[];
  deleted: DeletedTombstones;
}

// ----- PUSH (/sync) -----

export type SyncEntity =
  | 'progress_update'
  | 'inspection'
  | 'issue'
  | 'issue_task'
  | 'issue_comment'
  | 'feature';

export type SyncOp = 'create' | 'update';

export interface Operation {
  entity: SyncEntity;
  op: SyncOp;
  uuid: string;
  client_updated_at: string;
  data: Record<string, unknown>;
}

export type OperationStatus = 'applied' | 'duplicate' | 'conflict' | 'error';

export interface OperationResult {
  uuid: string;
  status: OperationStatus;
  server_id?: number | null;
  error?: string | null;
  server?: Record<string, unknown> | null;
}

export interface SyncResponse {
  results: OperationResult[];
}

// ----- Media (/media) -----

export interface MediaUploadResult {
  status: 'applied' | 'duplicate';
  media?: Media;
}
