-- Migration 181: FedEx shipments foundation (case-linked)

CREATE TABLE IF NOT EXISTS fedex_shipments (
    id SERIAL PRIMARY KEY,
    booking_ref VARCHAR(64) NOT NULL UNIQUE,
    case_id INTEGER NOT NULL REFERENCES sag_sager(id) ON DELETE CASCADE,
    customer_id INTEGER REFERENCES customers(id) ON DELETE SET NULL,
    contact_id INTEGER REFERENCES contacts(id) ON DELETE SET NULL,

    service_type VARCHAR(32) NOT NULL,
    shipment_status VARCHAR(32) NOT NULL DEFAULT 'draft',

    pickup_window_start TIMESTAMP NOT NULL,
    pickup_window_end TIMESTAMP NOT NULL,

    recipient_name VARCHAR(150) NOT NULL,
    company_name VARCHAR(150),
    address_line1 VARCHAR(200) NOT NULL,
    address_line2 VARCHAR(200),
    postal_code VARCHAR(20) NOT NULL,
    city VARCHAR(120) NOT NULL,
    country_code VARCHAR(2) NOT NULL,
    phone VARCHAR(50),
    email VARCHAR(150),

    tracking_number VARCHAR(64),
    label_url TEXT,
    cancel_reason TEXT,

    dry_run BOOLEAN NOT NULL DEFAULT FALSE,
    submitted_at TIMESTAMP,

    api_payload JSONB,
    api_response JSONB,

    created_by_user_id INTEGER REFERENCES users(user_id) ON DELETE SET NULL,
    updated_by_user_id INTEGER REFERENCES users(user_id) ON DELETE SET NULL,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP,

    CONSTRAINT fedex_shipments_service_type_check CHECK (service_type IN ('PRIORITY', 'ECONOMY')),
    CONSTRAINT fedex_shipments_status_check CHECK (
        shipment_status IN ('draft', 'submitted', 'booked', 'in_transit', 'delivered', 'cancelled', 'failed')
    ),
    CONSTRAINT fedex_shipments_pickup_window_check CHECK (pickup_window_end > pickup_window_start)
);

CREATE TABLE IF NOT EXISTS fedex_shipment_packages (
    id SERIAL PRIMARY KEY,
    shipment_id INTEGER NOT NULL REFERENCES fedex_shipments(id) ON DELETE CASCADE,
    weight_kg NUMERIC(10,3) NOT NULL,
    length_cm NUMERIC(10,2) NOT NULL,
    width_cm NUMERIC(10,2) NOT NULL,
    height_cm NUMERIC(10,2) NOT NULL,
    description VARCHAR(255) NOT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT fedex_package_weight_positive CHECK (weight_kg > 0),
    CONSTRAINT fedex_package_length_positive CHECK (length_cm > 0),
    CONSTRAINT fedex_package_width_positive CHECK (width_cm > 0),
    CONSTRAINT fedex_package_height_positive CHECK (height_cm > 0)
);

CREATE TABLE IF NOT EXISTS fedex_tracking_events (
    id SERIAL PRIMARY KEY,
    shipment_id INTEGER NOT NULL REFERENCES fedex_shipments(id) ON DELETE CASCADE,
    status VARCHAR(64) NOT NULL,
    description TEXT,
    event_timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    location_city VARCHAR(120),
    location_country VARCHAR(2),
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_fedex_shipments_case_id ON fedex_shipments(case_id);
CREATE INDEX IF NOT EXISTS idx_fedex_shipments_status ON fedex_shipments(shipment_status);
CREATE INDEX IF NOT EXISTS idx_fedex_shipments_tracking_number ON fedex_shipments(tracking_number);
CREATE INDEX IF NOT EXISTS idx_fedex_shipments_created_at ON fedex_shipments(created_at DESC);
CREATE INDEX IF NOT EXISTS idx_fedex_packages_shipment_id ON fedex_shipment_packages(shipment_id);
CREATE INDEX IF NOT EXISTS idx_fedex_tracking_shipment_id ON fedex_tracking_events(shipment_id);
CREATE INDEX IF NOT EXISTS idx_fedex_tracking_event_timestamp ON fedex_tracking_events(event_timestamp DESC);

CREATE OR REPLACE FUNCTION update_fedex_shipments_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS fedex_shipments_updated_at_trigger ON fedex_shipments;
CREATE TRIGGER fedex_shipments_updated_at_trigger
    BEFORE UPDATE ON fedex_shipments
    FOR EACH ROW
    EXECUTE FUNCTION update_fedex_shipments_updated_at();
