-- ===========================================
-- MECANICAS DIESEL - Tracking de Garantias
-- ===========================================
-- Resuelve: GAP-10
-- Sistema de seguimiento de garantias de refacciones
-- Permite reclamar garantias a proveedores

-- ============================================
-- EXTENSION DE PARTS PARA GARANTIAS
-- ============================================

-- Agregar campos de garantia a parts si no existen
DO $$
BEGIN
    -- warranty_months
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.columns
        WHERE table_schema = 'parts_management'
          AND table_name = 'parts'
          AND column_name = 'warranty_months'
    ) THEN
        ALTER TABLE parts_management.parts
        ADD COLUMN warranty_months INTEGER DEFAULT 0;
        COMMENT ON COLUMN parts_management.parts.warranty_months IS 'Meses de garantia del fabricante';
    END IF;

    -- warranty_policy
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.columns
        WHERE table_schema = 'parts_management'
          AND table_name = 'parts'
          AND column_name = 'warranty_policy'
    ) THEN
        ALTER TABLE parts_management.parts
        ADD COLUMN warranty_policy TEXT;
        COMMENT ON COLUMN parts_management.parts.warranty_policy IS 'Descripcion de politica de garantia';
    END IF;
END $$;

-- ============================================
-- TABLA DE GARANTIAS DE PARTES INSTALADAS
-- ============================================

-- Estados de garantia
CREATE TYPE parts_management.warranty_status AS ENUM (
    'active',       -- Garantia vigente
    'expired',      -- Garantia expirada
    'claimed',      -- Reclamo en proceso
    'approved',     -- Reclamo aprobado
    'rejected',     -- Reclamo rechazado
    'replaced'      -- Pieza reemplazada por garantia
);

-- Garantias de piezas instaladas
CREATE TABLE parts_management.warranty_claims (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,

    -- Referencia a la pieza
    part_id UUID NOT NULL,
    part_name VARCHAR(256) NOT NULL,           -- Desnormalizado para historial
    part_sku VARCHAR(50),

    -- Referencia al proveedor/fabricante
    supplier_id UUID,
    supplier_name VARCHAR(256),
    manufacturer VARCHAR(256),

    -- Datos de instalacion
    service_order_id UUID,
    service_order_number VARCHAR(50),
    installation_date DATE NOT NULL,
    installation_notes TEXT,

    -- Datos de garantia
    warranty_months INTEGER NOT NULL DEFAULT 12,
    expiration_date DATE NOT NULL,
    serial_number VARCHAR(100),
    lot_number VARCHAR(100),

    -- Vehiculo (contexto)
    vehicle_id UUID,
    vehicle_plate VARCHAR(20),
    vehicle_description VARCHAR(256),

    -- Cliente
    customer_id UUID,
    customer_name VARCHAR(256),

    -- Estado y reclamo
    status parts_management.warranty_status NOT NULL DEFAULT 'active',

    -- Datos del reclamo (si aplica)
    claim_date DATE,
    claim_reason TEXT,
    claim_description TEXT,
    defect_photos TEXT[],                      -- URLs de fotos del defecto

    -- Resolucion
    resolution_date DATE,
    resolution_type VARCHAR(50),               -- replacement, refund, repair, rejected
    resolution_notes TEXT,
    replacement_part_id UUID,                  -- Nueva pieza si fue reemplazo

    -- Costos
    original_cost DECIMAL(20,6),
    claim_amount DECIMAL(20,6),
    approved_amount DECIMAL(20,6),

    -- Auditoria
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ,
    created_by UUID,
    claimed_by UUID,
    resolved_by UUID
);

COMMENT ON TABLE parts_management.warranty_claims IS 'Registro de garantias de piezas instaladas en vehiculos';
COMMENT ON COLUMN parts_management.warranty_claims.defect_photos IS 'Array de URLs a fotos del defecto';

-- Indices para warranty_claims
CREATE INDEX idx_wc_tenant ON parts_management.warranty_claims(tenant_id);
CREATE INDEX idx_wc_part ON parts_management.warranty_claims(part_id);
CREATE INDEX idx_wc_service_order ON parts_management.warranty_claims(service_order_id) WHERE service_order_id IS NOT NULL;
CREATE INDEX idx_wc_vehicle ON parts_management.warranty_claims(vehicle_id) WHERE vehicle_id IS NOT NULL;
CREATE INDEX idx_wc_customer ON parts_management.warranty_claims(customer_id);
CREATE INDEX idx_wc_status ON parts_management.warranty_claims(status);
CREATE INDEX idx_wc_expiration ON parts_management.warranty_claims(expiration_date)
    WHERE status = 'active';
CREATE INDEX idx_wc_supplier ON parts_management.warranty_claims(supplier_id) WHERE supplier_id IS NOT NULL;

-- RLS para warranty_claims
SELECT create_tenant_rls_policies('parts_management', 'warranty_claims');

-- Trigger para updated_at
CREATE TRIGGER set_updated_at_warranty_claims
    BEFORE UPDATE ON parts_management.warranty_claims
    FOR EACH ROW
    EXECUTE FUNCTION trigger_set_updated_at();

-- ============================================
-- FUNCIONES AUXILIARES
-- ============================================

-- Funcion para crear registro de garantia al instalar pieza
CREATE OR REPLACE FUNCTION parts_management.create_warranty_record(
    p_tenant_id UUID,
    p_part_id UUID,
    p_service_order_id UUID,
    p_vehicle_id UUID DEFAULT NULL,
    p_customer_id UUID DEFAULT NULL,
    p_serial_number VARCHAR(100) DEFAULT NULL,
    p_supplier_id UUID DEFAULT NULL
)
RETURNS UUID AS $$
DECLARE
    v_warranty_id UUID;
    v_part RECORD;
    v_service_order RECORD;
    v_vehicle RECORD;
    v_customer RECORD;
    v_supplier RECORD;
BEGIN
    -- Obtener datos de la pieza
    SELECT id, sku, name, warranty_months, warranty_policy, cost
    INTO v_part
    FROM parts_management.parts
    WHERE id = p_part_id;

    IF v_part.id IS NULL THEN
        RAISE EXCEPTION 'Part % not found', p_part_id;
    END IF;

    -- Si no tiene garantia, no crear registro
    IF COALESCE(v_part.warranty_months, 0) <= 0 THEN
        RETURN NULL;
    END IF;

    -- Obtener datos de orden de servicio
    SELECT id, order_number
    INTO v_service_order
    FROM service_management.service_orders
    WHERE id = p_service_order_id;

    -- Obtener datos de vehiculo (si aplica)
    IF p_vehicle_id IS NOT NULL THEN
        SELECT id, plate_number,
               CONCAT(brand, ' ', model, ' ', COALESCE(year::TEXT, '')) as description
        INTO v_vehicle
        FROM vehicle_management.vehicles
        WHERE id = p_vehicle_id;
    END IF;

    -- Obtener datos de cliente (si aplica)
    IF p_customer_id IS NOT NULL THEN
        SELECT id, name
        INTO v_customer
        FROM workshop_core.customers
        WHERE id = p_customer_id;
    END IF;

    -- Obtener datos de proveedor (si aplica)
    IF p_supplier_id IS NOT NULL THEN
        SELECT id, name
        INTO v_supplier
        FROM purchasing.suppliers
        WHERE id = p_supplier_id;
    END IF;

    -- Crear registro de garantia
    INSERT INTO parts_management.warranty_claims (
        tenant_id,
        part_id, part_name, part_sku,
        supplier_id, supplier_name,
        service_order_id, service_order_number,
        installation_date, warranty_months, expiration_date,
        serial_number,
        vehicle_id, vehicle_plate, vehicle_description,
        customer_id, customer_name,
        original_cost,
        created_by
    )
    VALUES (
        p_tenant_id,
        v_part.id, v_part.name, v_part.sku,
        p_supplier_id, v_supplier.name,
        p_service_order_id, v_service_order.order_number,
        CURRENT_DATE, v_part.warranty_months,
        CURRENT_DATE + (v_part.warranty_months || ' months')::INTERVAL,
        p_serial_number,
        p_vehicle_id, v_vehicle.plate_number, v_vehicle.description,
        p_customer_id, v_customer.name,
        v_part.cost,
        get_current_user_id()
    )
    RETURNING id INTO v_warranty_id;

    RETURN v_warranty_id;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION parts_management.create_warranty_record IS 'Crea registro de garantia al instalar una pieza';

-- Funcion para iniciar reclamo de garantia
CREATE OR REPLACE FUNCTION parts_management.initiate_warranty_claim(
    p_warranty_id UUID,
    p_claim_reason TEXT,
    p_claim_description TEXT DEFAULT NULL,
    p_defect_photos TEXT[] DEFAULT NULL
)
RETURNS BOOLEAN AS $$
DECLARE
    v_warranty RECORD;
BEGIN
    -- Obtener garantia
    SELECT * INTO v_warranty
    FROM parts_management.warranty_claims
    WHERE id = p_warranty_id;

    IF v_warranty.id IS NULL THEN
        RAISE EXCEPTION 'Warranty record % not found', p_warranty_id;
    END IF;

    -- Verificar que este activa
    IF v_warranty.status != 'active' THEN
        RAISE EXCEPTION 'Warranty is not active (current status: %)', v_warranty.status;
    END IF;

    -- Verificar que no este expirada
    IF v_warranty.expiration_date < CURRENT_DATE THEN
        -- Actualizar a expirada primero
        UPDATE parts_management.warranty_claims
        SET status = 'expired', updated_at = NOW()
        WHERE id = p_warranty_id;

        RAISE EXCEPTION 'Warranty expired on %', v_warranty.expiration_date;
    END IF;

    -- Actualizar con datos del reclamo
    UPDATE parts_management.warranty_claims
    SET
        status = 'claimed',
        claim_date = CURRENT_DATE,
        claim_reason = p_claim_reason,
        claim_description = p_claim_description,
        defect_photos = p_defect_photos,
        claim_amount = original_cost,
        claimed_by = get_current_user_id(),
        updated_at = NOW()
    WHERE id = p_warranty_id;

    RETURN TRUE;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION parts_management.initiate_warranty_claim IS 'Inicia un reclamo de garantia';

-- Funcion para resolver reclamo
CREATE OR REPLACE FUNCTION parts_management.resolve_warranty_claim(
    p_warranty_id UUID,
    p_resolution_type VARCHAR(50),
    p_approved_amount DECIMAL(20,6) DEFAULT NULL,
    p_resolution_notes TEXT DEFAULT NULL,
    p_replacement_part_id UUID DEFAULT NULL
)
RETURNS BOOLEAN AS $$
DECLARE
    v_new_status parts_management.warranty_status;
BEGIN
    -- Determinar nuevo estado segun resolucion
    v_new_status := CASE p_resolution_type
        WHEN 'replacement' THEN 'replaced'::parts_management.warranty_status
        WHEN 'refund' THEN 'approved'::parts_management.warranty_status
        WHEN 'repair' THEN 'approved'::parts_management.warranty_status
        WHEN 'rejected' THEN 'rejected'::parts_management.warranty_status
        ELSE 'approved'::parts_management.warranty_status
    END;

    UPDATE parts_management.warranty_claims
    SET
        status = v_new_status,
        resolution_date = CURRENT_DATE,
        resolution_type = p_resolution_type,
        resolution_notes = p_resolution_notes,
        approved_amount = CASE
            WHEN p_resolution_type = 'rejected' THEN 0
            ELSE COALESCE(p_approved_amount, claim_amount)
        END,
        replacement_part_id = p_replacement_part_id,
        resolved_by = get_current_user_id(),
        updated_at = NOW()
    WHERE id = p_warranty_id
      AND status = 'claimed';

    RETURN FOUND;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION parts_management.resolve_warranty_claim IS 'Resuelve un reclamo de garantia';

-- Funcion para actualizar garantias expiradas (ejecutar diariamente)
CREATE OR REPLACE FUNCTION parts_management.expire_warranties()
RETURNS INTEGER AS $$
DECLARE
    v_count INTEGER;
BEGIN
    UPDATE parts_management.warranty_claims
    SET
        status = 'expired',
        updated_at = NOW()
    WHERE status = 'active'
      AND expiration_date < CURRENT_DATE;

    GET DIAGNOSTICS v_count = ROW_COUNT;
    RETURN v_count;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION parts_management.expire_warranties IS 'Marca como expiradas las garantias vencidas';

-- ============================================
-- VISTAS DE REPORTES
-- ============================================

-- Vista de garantias activas
CREATE VIEW parts_management.v_active_warranties AS
SELECT
    wc.id,
    wc.tenant_id,
    wc.part_id,
    wc.part_name,
    wc.part_sku,
    wc.supplier_name,
    wc.manufacturer,
    wc.service_order_number,
    wc.installation_date,
    wc.expiration_date,
    wc.serial_number,
    wc.vehicle_plate,
    wc.vehicle_description,
    wc.customer_name,
    wc.original_cost,
    -- Dias restantes
    wc.expiration_date - CURRENT_DATE as days_remaining,
    -- Urgencia de expiracion
    CASE
        WHEN wc.expiration_date - CURRENT_DATE <= 7 THEN 'critical'
        WHEN wc.expiration_date - CURRENT_DATE <= 30 THEN 'warning'
        WHEN wc.expiration_date - CURRENT_DATE <= 90 THEN 'notice'
        ELSE 'ok'
    END as expiration_urgency
FROM parts_management.warranty_claims wc
WHERE wc.status = 'active'
  AND wc.expiration_date >= CURRENT_DATE
ORDER BY wc.expiration_date ASC;

COMMENT ON VIEW parts_management.v_active_warranties IS 'Garantias vigentes con dias restantes';

-- Vista de reclamos pendientes
CREATE VIEW parts_management.v_pending_claims AS
SELECT
    wc.id,
    wc.tenant_id,
    wc.part_name,
    wc.part_sku,
    wc.supplier_id,
    wc.supplier_name,
    wc.claim_date,
    wc.claim_reason,
    wc.claim_amount,
    wc.vehicle_plate,
    wc.customer_name,
    CURRENT_DATE - wc.claim_date as days_pending
FROM parts_management.warranty_claims wc
WHERE wc.status = 'claimed'
ORDER BY wc.claim_date ASC;

COMMENT ON VIEW parts_management.v_pending_claims IS 'Reclamos de garantia pendientes de resolucion';

-- Vista resumen de garantias por proveedor
CREATE VIEW parts_management.v_warranty_summary_by_supplier AS
SELECT
    wc.tenant_id,
    wc.supplier_id,
    wc.supplier_name,
    COUNT(*) as total_warranties,
    COUNT(*) FILTER (WHERE status = 'active') as active_warranties,
    COUNT(*) FILTER (WHERE status = 'claimed') as pending_claims,
    COUNT(*) FILTER (WHERE status IN ('approved', 'replaced')) as approved_claims,
    COUNT(*) FILTER (WHERE status = 'rejected') as rejected_claims,
    COALESCE(SUM(approved_amount) FILTER (WHERE status IN ('approved', 'replaced')), 0) as total_approved_amount,
    ROUND(
        COUNT(*) FILTER (WHERE status IN ('approved', 'replaced'))::DECIMAL /
        NULLIF(COUNT(*) FILTER (WHERE status IN ('approved', 'replaced', 'rejected')), 0) * 100,
        2
    ) as approval_rate
FROM parts_management.warranty_claims wc
WHERE wc.supplier_id IS NOT NULL
GROUP BY wc.tenant_id, wc.supplier_id, wc.supplier_name
ORDER BY total_warranties DESC;

COMMENT ON VIEW parts_management.v_warranty_summary_by_supplier IS 'Resumen de garantias agrupado por proveedor';

-- Vista de garantias por vehiculo
CREATE VIEW parts_management.v_vehicle_warranties AS
SELECT
    wc.tenant_id,
    wc.vehicle_id,
    wc.vehicle_plate,
    wc.vehicle_description,
    wc.customer_id,
    wc.customer_name,
    COUNT(*) as total_parts_with_warranty,
    COUNT(*) FILTER (WHERE status = 'active' AND expiration_date >= CURRENT_DATE) as active_warranties,
    COUNT(*) FILTER (WHERE status = 'active' AND expiration_date >= CURRENT_DATE AND expiration_date - CURRENT_DATE <= 30) as expiring_soon,
    COALESCE(SUM(original_cost), 0) as total_warranty_value
FROM parts_management.warranty_claims wc
WHERE wc.vehicle_id IS NOT NULL
GROUP BY wc.tenant_id, wc.vehicle_id, wc.vehicle_plate, wc.vehicle_description,
         wc.customer_id, wc.customer_name
ORDER BY active_warranties DESC;

COMMENT ON VIEW parts_management.v_vehicle_warranties IS 'Resumen de garantias por vehiculo';

-- ============================================
-- GRANTS
-- ============================================
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA parts_management TO mecanicas_user;
GRANT SELECT ON ALL TABLES IN SCHEMA parts_management TO mecanicas_user;
