import { HttpClient } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from '../../environments/environment';
import { StaffUser } from './auth.service';

export interface MatchResult {
  hall_id: number; hall_name: string; venue_name: string;
  score: number; matched: boolean; reasons: string[];
}
export interface LeadRow {
  id: number; stage: string; event_type?: string; attendees?: number; budget_max?: number;
  contact?: { name: string; mobile: string }; created_at?: string;
}
export interface Dashboard {
  leads_total: number; leads_by_stage: Record<string, number>;
  bookings_total: number; upcoming_visits: number; halls_total: number; venues_total: number;
  tasks_open?: number; tasks_overdue?: number; assets_total?: number; assets_maintenance?: number;
  upcoming_bookings?: UpcomingBooking[];
  revenue?: { invoiced: number; collected: number; due: number; collected_pct: number };
}
export interface UpcomingBooking {
  id: number; booking_no: string; event_date: string | null; event_type?: string; status: string; attendees?: number; contact?: string;
}
export interface LeadDetail {
  id: number; stage: string; source?: string; event_type?: string; attendees?: number;
  fnb_level?: string; venue_preference?: string; budget_max?: number; candidate_dates?: string[];
  contact?: { name: string; mobile: string; email?: string };
  halls: LeadHallBreakdown[];
  grand_total?: number;
  visits: { date: string; time: string | null; status: string }[];
}
export interface LeadHallBreakdown {
  hall: string; package: string | null; package_price: number; score: number | null;
  total: number;
  addons: { name: string; qty: number; price: number }[];
  extras: { name: string; qty: number; price: number }[];
  swaps: { item: string; label: string; delta: number }[];
}

export interface PaymentScheduleRow {
  id: number; label: string; kind: string; due_date: string | null;
  percent: number; amount: number; paid_amount: number; due: number; status: string;
}
export interface BookingInfo {
  booking: {
    id: number; booking_no: string | null; status: string; event_date: string | null; total: number;
    penalty_amount?: number | null; refund_amount?: number | null;
    rescheduled_from?: string | null; reschedule_count?: number;
    cancelled_at?: string | null; contracted_at?: string | null; completed_at?: string | null;
  };
  invoice: { total: number; paid: number; due: number; status: string; invoice_no: string | null };
  schedule?: PaymentScheduleRow[];
  deposit_met?: boolean;
  cancellation?: CancelQuote;
  reschedule?: { from: string | null; to: string; penalty_percent: number; fee_amount: number };
  erp_invoice_id?: number | null;
}
export interface CancelQuote {
  days_to_event: number; penalty_percent: number; penalty_amount: number;
  total: number; paid: number; refund_amount: number; overridden?: boolean;
}
export interface CancelReason { code: string; en: string; ar: string; }
export interface CancelQuoteResponse { quote: CancelQuote; policy: any; reasons?: CancelReason[]; can_override: boolean; }
export interface BookingEvent { id: number; type: string; payload: any; at: string | null; }
export interface BookingDoc { id: number; type: string; version: number; accepted_at?: string | null; at?: string | null; }
export interface ChangeReq {
  id: number; type: string; message: string; status: string; staff_note: string | null;
  booking_id: number | null; lead_id: number | null; contact: string | null; at: string | null;
}
export interface QcItem { label: string; label_ar?: string | null; status: 'pass' | 'fail' | 'na'; reason_code?: string | null; note?: string | null; }
export interface QcEvent { type: string; detail: string | null; user: string | null; at: string | null; }
export interface QcReason { code: string; en: string; ar: string; }
export interface QcInspection { id: number; booking_id: number; stage: string; status: string; score: number | null; items: QcItem[]; completed_at: string | null; events?: QcEvent[]; }
export interface StaffTask { id: number; title: string; department: string; due_at: string | null; role: string | null; status: string; }
export interface OpsTask extends StaffTask {
  overdue: boolean; booking_id: number; booking_no: string; event_date: string | null; contact: string | null;
  read?: boolean; accepted?: boolean;
}
export interface TaskEvent { type: string; note: string | null; user: string | null; at: string | null; }
export interface TaskDetail {
  id: number; title: string; department: string; status: string; due_at: string | null;
  received_at: string | null; read_at: string | null; accepted_at: string | null; events: TaskEvent[];
}

export interface TransferRow { id: number; type: string; status: string; to_hall: string | null; items_count: number; booking_id: number | null; accepted_at: string | null; }
export interface TransferItem { id: number; name: string; kind: string; quantity: number; accepted_quantity: number | null; condition: string | null; }
export interface TransferDetail {
  id: number; type: string; status: string; to_hall_id: number; booking_id: number | null;
  accepted_by: number | null; accepted_at: string | null; stock_refs: any; items: TransferItem[];
}
export interface HallOption { id: number; name: string; name_ar?: string; venue?: { name: string }; }
export interface AssetRow {
  id: number; code: string; name: string; category: string; condition: string; status: string;
  quantity: number; location_id: number | null; hall_id: number | null;
  location_name: string | null; hall_name: string | null;
}
export interface AssetMovement {
  id: number; from: string | null; to: string | null; condition: string | null;
  reason: string | null; notes: string | null; by: string | null; at: string | null;
}
export interface VisitRow {
  id: number; date: string | null; time: string | null; status: string; overdue: boolean;
  lead_id: number | null; contact: string | null; mobile: string | null; location: string | null;
}
export interface MaintenanceRow {
  id: number; code: string; title: string; category: string; priority: string;
  status: string; hall: string | null; due_at: string | null; overdue: boolean; mine: boolean;
}
export interface MaintenanceUpdate { id: number; from: string | null; to: string | null; comment: string | null; at: string | null; }
export interface MaintenanceDetail {
  id: number; code: string; title: string; description: string | null; category: string;
  priority: string; status: string; hall_id: number | null; asset_id: number | null;
  assigned_to: number | null; due_at: string | null; resolved_at: string | null; verified_at: string | null;
  flow: string[]; updates: MaintenanceUpdate[];
}
export interface AssetOption {
  id: number; code: string; name: string; category: string;
  condition: string; status: string; quantity: number;
  location_id: number | null; hall_id: number | null;
}

interface Envelope<T> { success: boolean; data: T; message?: string; }

@Injectable({ providedIn: 'root' })
export class ApiService {
  private http = inject(HttpClient);
  private base = environment.apiBase;

  login(username: string, password: string): Observable<Envelope<{ token: string; user: StaffUser; permissions: string[] }>> {
    return this.http.post<Envelope<{ token: string; user: StaffUser; permissions: string[] }>>(`${this.base}/employee/login`, { username, password });
  }
  devStaff(): Observable<Envelope<{ roles: { role: string; name: string; name_ar: string; username: string }[] }>> {
    return this.http.get<Envelope<{ roles: { role: string; name: string; name_ar: string; username: string }[] }>>(`${this.base}/employee/dev-staff`);
  }
  devStaffLogin(role: string): Observable<Envelope<{ token: string; user: StaffUser; permissions: string[] }>> {
    return this.http.post<Envelope<{ token: string; user: StaffUser; permissions: string[] }>>(`${this.base}/employee/dev-login`, { role });
  }
  dashboard(): Observable<Envelope<Dashboard>> {
    return this.http.get<Envelope<Dashboard>>(`${this.base}/employee/dashboard`);
  }
  leads(stage?: string): Observable<Envelope<{ leads: { data: LeadRow[]; total: number } }>> {
    const q = stage ? `?stage=${stage}` : '';
    return this.http.get<Envelope<{ leads: { data: LeadRow[]; total: number } }>>(`${this.base}/employee/leads${q}`);
  }
  lead(id: number): Observable<Envelope<{ lead: LeadDetail }>> {
    return this.http.get<Envelope<{ lead: LeadDetail }>>(`${this.base}/employee/leads/${id}`);
  }
  match(criteria: any): Observable<Envelope<{ threshold: number; matched_count: number; results: MatchResult[] }>> {
    return this.http.post<Envelope<{ threshold: number; matched_count: number; results: MatchResult[] }>>(`${this.base}/employee/match`, criteria);
  }
  reference(): Observable<Envelope<any>> {
    return this.http.get<Envelope<any>>(`${this.base}/reference`);
  }

  // ---- bookings / money path ----
  book(leadId: number, eventDate?: string): Observable<Envelope<BookingInfo>> {
    return this.http.post<Envelope<BookingInfo>>(`${this.base}/employee/leads/${leadId}/book`, eventDate ? { event_date: eventDate } : {});
  }
  booking(id: number): Observable<Envelope<BookingInfo>> {
    return this.http.get<Envelope<BookingInfo>>(`${this.base}/employee/bookings/${id}`);
  }
  confirmBooking(id: number): Observable<Envelope<BookingInfo>> {
    return this.http.post<Envelope<BookingInfo>>(`${this.base}/employee/bookings/${id}/confirm`, {});
  }
  contractBooking(id: number): Observable<Envelope<BookingInfo>> {
    return this.http.post<Envelope<BookingInfo>>(`${this.base}/employee/bookings/${id}/contract`, {});
  }
  completeBooking(id: number): Observable<Envelope<BookingInfo>> {
    return this.http.post<Envelope<BookingInfo>>(`${this.base}/employee/bookings/${id}/complete`, {});
  }
  cancelQuote(id: number, override?: number): Observable<Envelope<CancelQuoteResponse>> {
    const q = override != null ? `?override_penalty_percent=${override}` : '';
    return this.http.get<Envelope<CancelQuoteResponse>>(`${this.base}/employee/bookings/${id}/cancel-quote${q}`);
  }
  cancelBooking(id: number, payload: { reason?: string; reason_code?: string; override_penalty_percent?: number }): Observable<Envelope<BookingInfo>> {
    return this.http.post<Envelope<BookingInfo>>(`${this.base}/employee/bookings/${id}/cancel`, payload);
  }
  rescheduleQuote(id: number, override?: number): Observable<Envelope<CancelQuoteResponse>> {
    const q = override != null ? `?override_penalty_percent=${override}` : '';
    return this.http.get<Envelope<CancelQuoteResponse>>(`${this.base}/employee/bookings/${id}/reschedule-quote${q}`);
  }
  rescheduleBooking(id: number, payload: { event_date: string; override_penalty_percent?: number }): Observable<Envelope<BookingInfo>> {
    return this.http.post<Envelope<BookingInfo>>(`${this.base}/employee/bookings/${id}/reschedule`, payload);
  }
  bookingEvents(id: number): Observable<Envelope<{ events: BookingEvent[] }>> {
    return this.http.get<Envelope<{ events: BookingEvent[] }>>(`${this.base}/employee/bookings/${id}/events`);
  }
  bookingDocuments(id: number): Observable<Envelope<{ documents: BookingDoc[] }>> {
    return this.http.get<Envelope<{ documents: BookingDoc[] }>>(`${this.base}/employee/bookings/${id}/documents`);
  }
  generateDocument(id: number, type: string): Observable<Envelope<{ document: BookingDoc }>> {
    return this.http.post<Envelope<{ document: BookingDoc }>>(`${this.base}/employee/bookings/${id}/documents/${type}`, {});
  }
  downloadDocument(docId: number, lang?: string): Observable<Blob> {
    const q = lang ? `?lang=${lang}` : '';
    return this.http.get(`${this.base}/employee/documents/${docId}/download${q}`, { responseType: 'blob' });
  }
  qcInspection(bookingId: number, stage = 'pre_event'): Observable<Envelope<{ inspection: QcInspection; reasons: QcReason[] }>> {
    return this.http.get<Envelope<{ inspection: QcInspection; reasons: QcReason[] }>>(`${this.base}/employee/bookings/${bookingId}/qc?stage=${stage}`);
  }
  qcSubmit(inspId: number, items: QcItem[]): Observable<Envelope<{ inspection: QcInspection }>> {
    return this.http.post<Envelope<{ inspection: QcInspection }>>(`${this.base}/employee/qc/${inspId}/submit`, { items });
  }
  qcVoice(inspId: number, file: Blob): Observable<Envelope<{ inspection: QcInspection }>> {
    const fd = new FormData();
    fd.append('file', file, 'qc-voice.webm');
    return this.http.post<Envelope<{ inspection: QcInspection }>>(`${this.base}/employee/qc/${inspId}/voice`, fd);
  }
  aiChat(message: string, lang: string): Observable<Envelope<{ reply: string }>> {
    return this.http.post<Envelope<{ reply: string }>>(`${this.base}/employee/ai/chat`, { message, lang });
  }
  changeRequests(status = 'pending'): Observable<Envelope<{ requests: ChangeReq[] }>> {
    return this.http.get<Envelope<{ requests: ChangeReq[] }>>(`${this.base}/employee/change-requests?status=${status}`);
  }
  decideChangeRequest(id: number, status: 'approved' | 'rejected', note?: string): Observable<Envelope<{ id: number; status: string }>> {
    return this.http.post<Envelope<{ id: number; status: string }>>(`${this.base}/employee/change-requests/${id}/decide`, { status, note });
  }
  recordPayment(id: number, payment: { amount: number; method?: string; note?: string }): Observable<Envelope<BookingInfo>> {
    return this.http.post<Envelope<BookingInfo>>(`${this.base}/employee/bookings/${id}/payments`, payment);
  }
  bookingTasks(id: number): Observable<Envelope<{ tasks: StaffTask[] }>> {
    return this.http.get<Envelope<{ tasks: StaffTask[] }>>(`${this.base}/employee/bookings/${id}/tasks`);
  }
  completeTask(id: number): Observable<Envelope<{ id: number; status: string }>> {
    return this.http.post<Envelope<{ id: number; status: string }>>(`${this.base}/employee/tasks/${id}/complete`, {});
  }
  taskDetail(id: number): Observable<Envelope<{ task: TaskDetail }>> {
    return this.http.get<Envelope<{ task: TaskDetail }>>(`${this.base}/employee/tasks/${id}`);
  }
  acceptTask(id: number): Observable<Envelope<{ task: TaskDetail }>> {
    return this.http.post<Envelope<{ task: TaskDetail }>>(`${this.base}/employee/tasks/${id}/accept`, {});
  }
  opsTasks(status: string, department?: string): Observable<Envelope<{ tasks: OpsTask[]; departments: string[] }>> {
    let q = `?status=${status}`;
    if (department) { q += `&department=${encodeURIComponent(department)}`; }
    return this.http.get<Envelope<{ tasks: OpsTask[]; departments: string[] }>>(`${this.base}/employee/tasks${q}`);
  }

  // ---- transfers + acceptance audit ----
  halls(): Observable<Envelope<{ halls: HallOption[] }>> {
    return this.http.get<Envelope<{ halls: HallOption[] }>>(`${this.base}/halls`);
  }
  assetRegister(q?: string, status?: string, category?: string): Observable<Envelope<{ assets: AssetRow[]; categories: string[]; statuses: string[] }>> {
    const p = new URLSearchParams();
    if (q) { p.set('q', q); }
    if (status) { p.set('status', status); }
    if (category) { p.set('category', category); }
    const qs = p.toString();
    return this.http.get<Envelope<{ assets: AssetRow[]; categories: string[]; statuses: string[] }>>(`${this.base}/employee/assets${qs ? '?' + qs : ''}`);
  }
  relocateAsset(id: number, payload: { hall_id?: number; location_id?: number; condition?: string; notes?: string }): Observable<Envelope<{ id: number }>> {
    return this.http.post<Envelope<{ id: number }>>(`${this.base}/employee/assets/${id}/relocate`, payload);
  }
  assetHistory(id: number): Observable<Envelope<{ asset: { code: string; name: string }; movements: AssetMovement[] }>> {
    return this.http.get<Envelope<{ asset: { code: string; name: string }; movements: AssetMovement[] }>>(`${this.base}/employee/assets/${id}/history`);
  }
  visits(status: string): Observable<Envelope<{ visits: VisitRow[] }>> {
    return this.http.get<Envelope<{ visits: VisitRow[] }>>(`${this.base}/employee/visits?status=${status}`);
  }

  // ---- maintenance ----
  maintenance(status?: string, scope?: string): Observable<Envelope<{ requests: MaintenanceRow[] }>> {
    const p = new URLSearchParams();
    if (status) { p.set('status', status); }
    if (scope) { p.set('scope', scope); }
    const qs = p.toString();
    return this.http.get<Envelope<{ requests: MaintenanceRow[] }>>(`${this.base}/employee/maintenance${qs ? '?' + qs : ''}`);
  }
  maintenanceDetail(id: number): Observable<Envelope<{ request: MaintenanceDetail }>> {
    return this.http.get<Envelope<{ request: MaintenanceDetail }>>(`${this.base}/employee/maintenance/${id}`);
  }
  createMaintenance(payload: { title: string; description?: string; hall_id?: number; category?: string; priority?: string }): Observable<Envelope<{ id: number; code: string }>> {
    return this.http.post<Envelope<{ id: number; code: string }>>(`${this.base}/employee/maintenance`, payload);
  }
  transitionMaintenance(id: number, payload: { to: string; comment?: string; assign_to?: number }): Observable<Envelope<{ request: MaintenanceDetail }>> {
    return this.http.post<Envelope<{ request: MaintenanceDetail }>>(`${this.base}/employee/maintenance/${id}/transition`, payload);
  }
  assets(): Observable<Envelope<{ assets: AssetOption[] }>> {
    return this.http.get<Envelope<{ assets: AssetOption[] }>>(`${this.base}/employee/assets?available_only=1`);
  }
  transfers(status?: string): Observable<Envelope<{ transfers: { data: TransferRow[]; total: number } }>> {
    const q = status ? `?status=${status}` : '';
    return this.http.get<Envelope<{ transfers: { data: TransferRow[]; total: number } }>>(`${this.base}/employee/transfers${q}`);
  }
  transfer(id: number): Observable<Envelope<{ transfer: TransferDetail }>> {
    return this.http.get<Envelope<{ transfer: TransferDetail }>>(`${this.base}/employee/transfers/${id}`);
  }
  createTransfer(payload: any): Observable<Envelope<{ transfer: TransferDetail }>> {
    return this.http.post<Envelope<{ transfer: TransferDetail }>>(`${this.base}/employee/transfers`, payload);
  }
  acceptTransfer(id: number, items: Record<number, { accepted_quantity?: number; condition?: string }>): Observable<Envelope<{ transfer: TransferDetail }>> {
    return this.http.post<Envelope<{ transfer: TransferDetail }>>(`${this.base}/employee/transfers/${id}/accept`, { items });
  }
}
