export type VesselCategory = 'INLAND_WATERWAY' | 'SEA_GOING';
export type VesselStatus = 'REGISTERED' | 'SUSPENDED' | 'DEREGISTERED';

/** A vessel-register entry, written when a registration certificate issues. */
export interface Vessel {
  id: string;
  registrationNumber: string;
  name: string;
  category: VesselCategory;
  vesselType: string | null;
  imoNumber: string | null;
  hullNumber: string | null;
  flagState: string | null;
  portOfRegistry: string | null;
  grossTonnage: string | number | null;
  passengerCapacity: number | null;
  lengthMeters: string | number | null;
  yearBuilt: number | null;
  engineType: string | null;
  enginePowerKw: string | number | null;
  numberOfEngines: number | null;
  hullMaterial: string | null;
  ownerUserId: string;
  ownerProfileId: string | null;
  ownerName: string | null;
  applicationId: string;
  licenseId: string;
  status: VesselStatus;
  statusReason: string | null;
  statusChangedAt: string | null;
  registeredAt: string;
}

export interface VesselIncident {
  id: string;
  vesselId: string;
  occurredAt: string;
  location: string | null;
  description: string;
  severity: string | null;
  reportedById: string;
  reportedByOfficer: boolean;
  createdAt: string;
}

export interface CreateVesselIncident {
  occurredAt: string;
  location?: string;
  description: string;
  severity?: string;
}

// ---------------------------------------------------------------------------
// Vessel registration report (GET /vessels/report)
//
// One call fills the whole backoffice dashboard. Unlike `Vessel` above, every
// numeric field here is already a real number — the API casts the Postgres
// `numeric` strings before it answers.

export type ReportGranularity = 'DAY' | 'WEEK' | 'MONTH';

/**
 * One slice of a breakdown chart.
 *
 * `percentage` is of the whole, not of the slices that survived the `topN`
 * cut, so a set of slices always totals 100.
 */
export interface BreakdownItem {
  key: string;
  label: string;
  count: number;
  percentage: number;
}

export interface VesselReportQuery {
  /** Bounds the time series and the "in period" figures only. */
  from?: string;
  to?: string;
  granularity?: ReportGranularity;
  category?: VesselCategory[];
  status?: VesselStatus[];
  flagState?: string[];
  portOfRegistry?: string[];
  vesselType?: string[];
  search?: string;
  expiringWithinDays?: number;
  /** Slices kept per high-cardinality chart; the tail collapses into "Other". */
  topN?: number;
  tableLimit?: number;
}

export interface RegisterKpis {
  total: number;
  registered: number;
  suspended: number;
  deregistered: number;
  registeredInPeriod: number;
  registeredInPreviousPeriod: number;
  /** Null when there is no previous period to compare against. */
  changePct: number | null;
}

export interface FleetKpis {
  totalGrossTonnage: number;
  avgGrossTonnage: number | null;
  /** How many hulls the tonnage average actually covers. */
  grossTonnageKnownFor: number;
  totalPassengerCapacity: number;
  avgLengthMeters: number | null;
  avgAgeYears: number | null;
  ageKnownFor: number;
  seaGoing: number;
  inlandWaterway: number;
}

export interface PipelineKpis {
  total: number;
  draft: number;
  inProgress: number;
  approved: number;
  rejected: number;
  issued: number;
  submittedInPeriod: number;
  decidedInPeriod: number;
  newCount: number;
  renewalCount: number;
  /** Approved over settled. Null while nothing has been decided. */
  approvalRatePct: number | null;
  avgProcessingDays: number | null;
  medianProcessingDays: number | null;
  avgAdjustmentRounds: number | null;
}

export interface CertificateKpis {
  total: number;
  active: number;
  expired: number;
  suspended: number;
  /** Cumulative: a certificate due in 11 days is inside all three. */
  expiringIn30: number;
  expiringIn60: number;
  expiringIn90: number;
  missingCertificate: number;
}

export interface IncidentKpis {
  total: number;
  inPeriod: number;
  reportedByOfficer: number;
  reportedByOwner: number;
  vesselsWithIncidents: number;
}

export interface RevenueKpis {
  currency: string;
  /** True when more than one currency was summed — warn rather than total. */
  mixedCurrency: boolean;
  paid: number;
  pending: number;
  paidCount: number;
  pendingCount: number;
  failedCount: number;
}

/** Bucketed series. `bucket` is an ISO date; the window is zero-filled. */
export interface RegistrationBucket {
  bucket: string;
  count: number;
  grossTonnage: number;
}

export interface ApplicationBucket {
  bucket: string;
  submitted: number;
  approved: number;
  rejected: number;
  issued: number;
}

export interface IncidentBucket {
  bucket: string;
  count: number;
}

export interface RevenueBucket {
  bucket: string;
  amount: number;
  count: number;
}

export interface ExpiringCertificateRow {
  vesselId: string;
  registrationNumber: string;
  name: string;
  ownerName: string | null;
  ownerUserId: string;
  certificateNumber: string | null;
  expiryDate: string;
  certificateStatus: string | null;
  /** 0 means it expires today, which still counts as live. */
  daysToExpiry: number;
}

export interface RecentRegistrationRow {
  vesselId: string;
  registrationNumber: string;
  name: string;
  category: VesselCategory;
  vesselType: string | null;
  flagState: string | null;
  grossTonnage: number | null;
  ownerName: string | null;
  status: VesselStatus;
  registeredAt: string;
}

export interface RecentIncidentRow {
  id: string;
  vesselId: string;
  registrationNumber: string;
  vesselName: string;
  occurredAt: string;
  severity: string | null;
  location: string | null;
  description: string;
  reportedByOfficer: boolean;
}

export interface PendingApplicationRow {
  applicationNumber: string;
  status: string;
  kind: 'NEW' | 'RENEWAL';
  assignedOfficerId: string | null;
  submittedAt: string | null;
  adjustmentRound: number;
  daysOpen: number;
}

export interface VesselReport {
  generatedAt: string;
  /** True when the register passed the API's scan cap — figures are partial. */
  truncated: boolean;
  filters: {
    from: string;
    to: string;
    granularity: ReportGranularity;
    expiringWithinDays: number;
    topN: number;
    tableLimit: number;
    category: VesselCategory[] | null;
    status: VesselStatus[] | null;
    flagState: string[] | null;
    portOfRegistry: string[] | null;
    vesselType: string[] | null;
    search: string | null;
  };
  kpis: {
    register: RegisterKpis;
    fleet: FleetKpis;
    pipeline: PipelineKpis;
    certificates: CertificateKpis;
    incidents: IncidentKpis;
    revenue: RevenueKpis;
  };
  timeSeries: {
    registrations: RegistrationBucket[];
    applications: ApplicationBucket[];
    incidents: IncidentBucket[];
    revenue: RevenueBucket[];
  };
  breakdowns: {
    byStatus: BreakdownItem[];
    byCategory: BreakdownItem[];
    byFlagState: BreakdownItem[];
    byPortOfRegistry: BreakdownItem[];
    byVesselType: BreakdownItem[];
    byHullMaterial: BreakdownItem[];
    byEngineType: BreakdownItem[];
    byTonnageBand: BreakdownItem[];
    byLengthBand: BreakdownItem[];
    byAgeBand: BreakdownItem[];
    byBuildDecade: BreakdownItem[];
    byApplicationStatus: BreakdownItem[];
    byApplicationKind: BreakdownItem[];
    /** `key` is an IAM user uuid, or the literal "UNASSIGNED". */
    byOfficer: BreakdownItem[];
    byIncidentSeverity: BreakdownItem[];
  };
  tables: {
    expiringCertificates: ExpiringCertificateRow[];
    recentRegistrations: RecentRegistrationRow[];
    recentIncidents: RecentIncidentRow[];
    pendingApplications: PendingApplicationRow[];
  };
}
