/**
 * Cliente API — Proceso comercial (Solicitudes/RFQ, tarifas, Cotizaciones).
 */
import { api } from '$lib/api';

// ---------- Tipos ----------
export type ServiceRequestStatus = 'nueva' | 'contacto' | 'en_analisis' | 'cotizada' | 'aceptada' | 'rechazada' | 'liberada';
export type QuoteStatus = 'borrador' | 'enviada' | 'aceptada' | 'rechazada';

export interface ServiceRequest {
	id: number;
	reference: string | null;
	case_id: number | null;
	account_id: number | null;
	contact_id: number | null;
	opportunity_id: number | null;
	operation_type: string;
	transport_mode: string | null;
	service_type: string | null;
	incoterm: string | null;
	origin: string | null;
	destination: string | null;
	origin_country: string | null;
	origin_city: string | null;
	origin_port: string | null;
	destination_country: string | null;
	destination_city: string | null;
	destination_port: string | null;
	pickup_location: string | null;
	delivery_location: string | null;
	cargo_type: string | null;
	weight: number | null;
	volume: number | null;
	load_type: string | null;
	container_equipment: string | null;
	container_count: number | null;
	commodity: string | null;
	required_date: string | null;
	request_date: string | null;
	estimated_shipment_date: string | null;
	currency: string | null;
	priority: string | null;
	cargo_value: number | null;
	insurance_required: boolean;
	hs_code: string | null;
	goods_origin_country: string | null;
	hazardous_imo: boolean;
	refrigerated: boolean;
	stackable: boolean;
	pieces_count: number | null;
	boxes_count: number | null;
	pallets_count: number | null;
	net_weight: number | null;
	length_cm: number | null;
	width_cm: number | null;
	height_cm: number | null;
	measurement_unit: string | null;
	packaging_type: string | null;
	oversized: boolean;
	weight_per_pallet: number | null;
	volume_per_pallet: number | null;
	additional_services: string[] | null;
	additional_service_costs: Record<string, number> | null;
	payment_method: string | null;
	destination_agent_id: number | null;
	requirements: string | null;
	client_notes: string | null;
	internal_notes: string | null;
	first_contact_at: string | null;
	first_contact_notes: string | null;
	status: ServiceRequestStatus;
	notes: string | null;
	owner_user_id: string | null;
	created_by: string | null;
	updated_by: string | null;
	tenant_id: number;
	company_id: number;
	created_at: string;
	updated_at: string;
}
export type ServiceRequestInput = Partial<Omit<ServiceRequest, 'id' | 'tenant_id' | 'company_id' | 'created_at' | 'updated_at' | 'created_by' | 'updated_by'>> & {
	operation_type: string;
};

export interface RateRequest {
	id: number;
	service_request_id: number;
	supplier_id: number | null;
	concept: string;
	description: string | null;
	status: string;
	rate_amount: number | null;
	currency: string | null;
	valid_until: string | null;
	notes: string | null;
	tenant_id: number;
	company_id: number;
	created_at: string;
	updated_at: string;
}
export type RateRequestInput = Partial<Omit<RateRequest, 'id' | 'tenant_id' | 'company_id' | 'created_at' | 'updated_at'>> & {
	service_request_id: number;
	concept: string;
};

export interface Quote {
	id: number;
	reference: string | null;
	service_request_id: number | null;
	service_request_reference: string | null;
	case_id: number | null;
	account_id: number | null;
	currency: string;
	load_type: string | null;
	status: QuoteStatus;
	issue_date: string | null;
	valid_until: string | null;
	total_cost: number;
	total_sale: number;
	margin: number;
	sent_at: string | null;
	accepted_at: string | null;
	rejected_at: string | null;
	notes: string | null;
	terms: string | null;
	owner_user_id: string | null;
	created_by: string | null;
	updated_by: string | null;
	tenant_id: number;
	company_id: number;
	created_at: string;
	updated_at: string;
}
export type QuoteInput = Partial<Omit<Quote, 'id' | 'status' | 'total_cost' | 'total_sale' | 'margin' | 'sent_at' | 'accepted_at' | 'rejected_at' | 'tenant_id' | 'company_id' | 'created_at' | 'updated_at' | 'created_by' | 'updated_by'>>;

export interface QuoteItem {
	id: number;
	quote_id: number;
	concept: string;
	description: string | null;
	supplier_id: number | null;
	quantity: number;
	unit_cost: number;
	unit_sale: number;
	currency: string | null;
	line_cost: number;
	line_sale: number;
	tenant_id: number;
	company_id: number;
}
export type QuoteItemInput = Partial<Omit<QuoteItem, 'id' | 'line_cost' | 'line_sale' | 'tenant_id' | 'company_id'>> & {
	quote_id: number;
	concept: string;
};

// ---------- Clientes ----------
function qp(companyId: number, extra?: Record<string, string | number | undefined>) {
	const qs = new URLSearchParams({ company_id: String(companyId) });
	for (const [k, v] of Object.entries(extra ?? {})) if (v !== undefined && v !== '') qs.set(k, String(v));
	return qs.toString();
}
async function unwrap<T>(p: Promise<{ data?: T; error?: string }>): Promise<T> {
	const res = await p;
	if (res.error) throw new Error(res.error);
	return res.data as T;
}

export const serviceRequestsAPI = {
	list: (companyId: number, params?: { search?: string; status?: string; operation_type?: string; account_id?: number }) =>
		unwrap<ServiceRequest[]>(api.get(`/v1/crm/service-requests?${qp(companyId, params)}`)),
	get: (id: number, companyId: number) => unwrap<ServiceRequest>(api.get(`/v1/crm/service-requests/${id}?${qp(companyId)}`)),
	create: (data: ServiceRequestInput, companyId: number) => unwrap<ServiceRequest>(api.post(`/v1/crm/service-requests?${qp(companyId)}`, data)),
	update: (id: number, data: Partial<ServiceRequestInput>, companyId: number) => unwrap<ServiceRequest>(api.patch(`/v1/crm/service-requests/${id}?${qp(companyId)}`, data)),
	registerContact: (id: number, companyId: number, notes?: string | null) =>
		unwrap<ServiceRequest>(api.post(`/v1/crm/service-requests/${id}/contact?${qp(companyId)}`, { notes })),
	requote: (id: number, companyId: number) =>
		unwrap<ServiceRequest>(api.post(`/v1/crm/service-requests/${id}/requote?${qp(companyId)}`, {})),
	fromOpportunity: (opportunityId: number, data: { operation_type?: string; transport_mode?: string; service_type?: string; incoterm?: string; origin?: string; destination?: string; notes?: string | null }, companyId: number) =>
		unwrap<ServiceRequest>(api.post(`/v1/crm/service-requests/from-opportunity?${qp(companyId, { opportunity_id: opportunityId })}`, data)),
	remove: (id: number, companyId: number) => unwrap(api.delete(`/v1/crm/service-requests/${id}?${qp(companyId)}`))
};

export const rateRequestsAPI = {
	list: (companyId: number, serviceRequestId?: number) =>
		unwrap<RateRequest[]>(api.get(`/v1/crm/rate-requests?${qp(companyId, { service_request_id: serviceRequestId })}`)),
	create: (data: RateRequestInput, companyId: number) => unwrap<RateRequest>(api.post(`/v1/crm/rate-requests?${qp(companyId)}`, data)),
	update: (id: number, data: Partial<RateRequestInput>, companyId: number) => unwrap<RateRequest>(api.patch(`/v1/crm/rate-requests/${id}?${qp(companyId)}`, data)),
	remove: (id: number, companyId: number) => unwrap(api.delete(`/v1/crm/rate-requests/${id}?${qp(companyId)}`))
};

export const quotesAPI = {
	list: (companyId: number, params?: { search?: string; status?: string; account_id?: number }) =>
		unwrap<Quote[]>(api.get(`/v1/crm/quotes?${qp(companyId, params)}`)),
	get: (id: number, companyId: number) => unwrap<Quote>(api.get(`/v1/crm/quotes/${id}?${qp(companyId)}`)),
	create: (data: QuoteInput, companyId: number) => unwrap<Quote>(api.post(`/v1/crm/quotes?${qp(companyId)}`, data)),
	update: (id: number, data: Partial<QuoteInput>, companyId: number) => unwrap<Quote>(api.patch(`/v1/crm/quotes/${id}?${qp(companyId)}`, data)),
	send: (id: number, companyId: number) => unwrap<Quote>(api.patch(`/v1/crm/quotes/${id}/send?${qp(companyId)}`, {})),
	accept: (id: number, companyId: number) => unwrap<Quote>(api.patch(`/v1/crm/quotes/${id}/accept?${qp(companyId)}`, {})),
	reject: (id: number, companyId: number) => unwrap<Quote>(api.patch(`/v1/crm/quotes/${id}/reject?${qp(companyId)}`, {})),
	clone: (id: number, companyId: number) => unwrap<Quote>(api.post(`/v1/crm/quotes/${id}/clone?${qp(companyId)}`, {})),
	fromServiceRequest: (serviceRequestId: number, companyId: number) =>
		unwrap<Quote[]>(api.post(`/v1/crm/quotes/from-service-request?${qp(companyId, { service_request_id: serviceRequestId })}`, {})),
	remove: (id: number, companyId: number) => unwrap(api.delete(`/v1/crm/quotes/${id}?${qp(companyId)}`)),
	items: (quoteId: number, companyId: number) => unwrap<QuoteItem[]>(api.get(`/v1/crm/quotes/${quoteId}/items?${qp(companyId)}`)),
	pdfBlob: (id: number, companyId: number) => (api as any).getBlob(`/v1/crm/quotes/${id}/pdf?${qp(companyId)}`) as Promise<Blob>,
	sendEmail: (id: number, companyId: number, body: { to?: string | null; subject?: string | null; message?: string | null }) =>
		unwrap<{ sent_to: string; reference: string }>(api.post(`/v1/crm/quotes/${id}/send-email?${qp(companyId)}`, body))
};

// ---------- Configuración de marca del formato de cotización ----------
export interface QuoteSettings {
	id?: number | null;
	emitter_name?: string | null; emitter_rfc?: string | null; emitter_address?: string | null;
	emitter_phone?: string | null; emitter_email?: string | null; emitter_website?: string | null;
	logo_file_key?: string | null; accent_color?: string | null; quote_prefix?: string | null;
	default_terms?: string | null; footer_note?: string | null;
}

export const quoteSettingsAPI = {
	get: (companyId: number) => unwrap<QuoteSettings>(api.get(`/v1/crm/quote-settings?${qp(companyId)}`)),
	save: (companyId: number, data: QuoteSettings) => unwrap<QuoteSettings>(api.put(`/v1/crm/quote-settings?${qp(companyId)}`, data)),
	logoUrl: (companyId: number) => unwrap<{ url: string | null }>(api.get(`/v1/crm/quote-settings/logo-url?${qp(companyId)}`)),
	async uploadLogo(companyId: number, file: File): Promise<QuoteSettings> {
		const fd = new FormData();
		fd.append('file', file);
		const res = await (api as any).request(`/v1/crm/quote-settings/logo?${qp(companyId)}`, { method: 'POST', body: fd });
		if (res.error) throw new Error(res.error);
		return res.data as QuoteSettings;
	}
};

// ---------- Catálogos de referencia (Incoterms, participantes) ----------
export interface Incoterm { code: string; name: string; }
export interface ParticipantRole { code: string; label: string; source: string; }
export interface Participant { id: number; source: string; name: string; role: string; roles: string[]; }

export const catalogsAPI = {
	incoterms: (companyId: number) => unwrap<Incoterm[]>(api.get(`/v1/crm/catalogs/incoterms?${qp(companyId)}`)),
	participantRoles: (companyId: number) => unwrap<ParticipantRole[]>(api.get(`/v1/crm/catalogs/participant-roles?${qp(companyId)}`)),
	participants: (companyId: number, role?: string) =>
		unwrap<Participant[]>(api.get(`/v1/crm/participants?${qp(companyId, { role })}`))
};

export const quoteItemsAPI = {
	create: (data: QuoteItemInput, companyId: number) => unwrap<QuoteItem>(api.post(`/v1/crm/quote-items?${qp(companyId)}`, data)),
	update: (id: number, data: Partial<QuoteItemInput>, companyId: number) => unwrap<QuoteItem>(api.patch(`/v1/crm/quote-items/${id}?${qp(companyId)}`, data)),
	remove: (id: number, companyId: number) => unwrap(api.delete(`/v1/crm/quote-items/${id}?${qp(companyId)}`))
};
