"/admin/dhl/invoices":
    get:
        tags: [DHL]
        operationId: getDHLInvoices
        summary: List DHL invoices
        description: Returns DHL invoices with optional filtering.
        parameters:
            - in: query
              name: status
              schema: { type: string }
              description: Invoice status filter.
            - in: query
              name: invoiceNumber
              schema: { type: string }
              description: Invoice number filter.
            - in: query
              name: limit
              schema: { type: integer }
            - in: query
              name: offset
              schema: { type: integer }
        responses:
            "200":
                description: Invoices page.
                content:
                    application/json:
                        schema:
                            type: object
                            required: [items, count]
                            properties:
                                items: { type: array, items: { $ref: "../components/schemas/DHLInvoice.yaml" } }
                                count: { type: integer }
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Inventory]
        x-scopes: ["shipping:read", "admin:all"]

"/admin/dhl/invoices/summary":
    get:
        tags: [DHL]
        operationId: getDHLInvoiceSummary
        summary: Aggregate totals across invoices + charges
        description: |
            Returns aggregate totals across the invoice + charge tables — used by Arda's
            DHL dashboard. **Note:** the handler swallows DB errors and returns all-zeros;
            check server logs if you see all-zero totals before assuming the DB is empty.
        responses:
            "200":
                description: Summary payload.
                content:
                    application/json:
                        schema:
                            type: object
                            required: [invoiceCount, totalValue, totalChargeCount]
                            properties:
                                invoiceCount:
                                    type: integer
                                    description: COUNT(*) on `big_dhl_invoices`.
                                totalValue:
                                    type: number
                                    description: SUM(totalAmount) on `big_dhl_invoices`, COALESCEd to 0.
                                totalChargeCount:
                                    type: integer
                                    description: COUNT(*) on `big_dhl_charges`.
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Inventory]
        x-scopes: ["shipping:read", "admin:all"]

"/admin/dhl/invoices/{id}":
    parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
    get:
        tags: [DHL]
        operationId: getDHLInvoice
        summary: Fetch a DHL invoice
        description: Returns a single DHL invoice by id.
        responses:
            "200":
                description: Invoice record.
                content:
                    application/json:
                        schema: { $ref: "../components/schemas/DHLInvoice.yaml" }
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
            "404":
                description: No invoice with this id.
                content:
                    application/json:
                        schema: { $ref: "../admin-api.yaml#/components/schemas/Error" }
        x-access-policies: [Admin, Inventory]
        x-scopes: ["shipping:read", "admin:all"]

"/admin/dhl/invoices/upload-csv":
    post:
        tags: [DHL]
        operationId: uploadDHLCSV
        summary: Ingest a DHL MyBill CSV
        description: |
            Ingests a DHL MyBill CSV export. Creates or updates invoices **and** their
            per-tracking-number charges in one pass. This is the only way to get DHL data
            into the system — there is no live Shippo API sync.

            Header matching is case-insensitive and strips non-alphanumeric characters
            (`Invoice Number` ≡ `invoice_number` ≡ `InvoiceNumber`). Rows without
            `invoiceNumber` are skipped (added to the response's `errors` array, not
            rejected). Duplicate `trackingNumber` values within a single CSV collapse
            into a single charge row (last-write-wins).
        requestBody:
            required: true
            content:
                multipart/form-data:
                    schema:
                        type: object
                        required: [file]
                        properties:
                            file:
                                type: string
                                format: binary
                                description: CSV file from DHL MyBill.
        responses:
            "200":
                description: Ingestion summary.
                content:
                    application/json:
                        schema:
                            type: object
                            required: [invoicesCreated, invoicesUpdated, chargesCreated, chargesUpdated, errors]
                            properties:
                                invoicesCreated: { type: integer, description: New `DHLInvoice` rows. }
                                invoicesUpdated: { type: integer, description: Existing `DHLInvoice` rows updated. }
                                chargesCreated: { type: integer, description: New `DHLCharge` rows. }
                                chargesUpdated:
                                    type: integer
                                    description: "Existing `DHLCharge` rows updated (upsert key `(invoiceId, trackingNumber)`)."
                                errors:
                                    type: array
                                    items: { type: string }
                                    description: Per-row non-fatal errors.
            "400":
                description: No file uploaded, parse error, no data rows, or missing invoice number column.
                content:
                    application/json:
                        schema: { $ref: "../admin-api.yaml#/components/schemas/Error" }
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Inventory]
        x-scopes: ["shipping:write", "admin:all"]

"/admin/dhl/charges":
    get:
        tags: [DHL]
        operationId: getDHLCharges
        summary: Browse charges
        description: Returns charges across invoices with paging and tracking-number substring search.
        parameters:
            - in: query
              name: invoiceId
              schema: { type: string }
              description: Exact match on `invoiceId`.
            - in: query
              name: trackingNumber
              schema: { type: string }
              description: ILIKE substring match (case-insensitive).
            - in: query
              name: invoiceNumber
              schema: { type: string }
              description: Exact match.
            - in: query
              name: limit
              schema: { type: integer, default: 100 }
            - in: query
              name: offset
              schema: { type: integer, default: 0 }
        responses:
            "200":
                description: Charges page.
                content:
                    application/json:
                        schema:
                            type: object
                            required: [items, count]
                            properties:
                                items:
                                    type: array
                                    items: { $ref: "../components/schemas/DHLCharge.yaml" }
                                count:
                                    type: integer
                                    description: Total matching rows (via `COUNT(*) OVER()`).
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Inventory]
        x-scopes: ["shipping:read", "admin:all"]

"/admin/dhl/charges/flagged":
    get:
        tags: [DHL]
        operationId: getDHLFlaggedCharges
        summary: List flagged charges
        description: Returns flagged charges with optional filtering. Flags are created by `POST /admin/dhl/reconcile`.
        parameters:
            - in: query
              name: invoiceId
              schema: { type: string }
            - in: query
              name: status
              schema: { type: string }
            - in: query
              name: trackingNumber
              schema: { type: string }
            - in: query
              name: limit
              schema: { type: integer }
            - in: query
              name: offset
              schema: { type: integer }
        responses:
            "200":
                description: Flagged charges page.
                content:
                    application/json:
                        schema:
                            type: object
                            required: [items, count]
                            properties:
                                items: { type: array, items: { $ref: "../components/schemas/DHLChargeFlag.yaml" } }
                                count: { type: integer }
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin, Inventory]
        x-scopes: ["shipping:read", "admin:all"]

"/admin/dhl/charges/{id}":
    parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
    put:
        tags: [DHL]
        operationId: updateDHLChargeFlag
        summary: Update a charge flag
        description: Updates a charge flag's status and/or notes.
        requestBody:
            required: true
            content:
                application/json:
                    schema:
                        type: object
                        properties:
                            status:
                                type: string
                                enum: [New, Reviewed, Resolved, Disputed]
                            notes: { type: string }
        responses:
            "200":
                description: Updated flag.
                content:
                    application/json:
                        schema: { $ref: "../components/schemas/DHLChargeFlag.yaml" }
            "400":
                description: Invalid `status`.
                content:
                    application/json:
                        schema: { $ref: "../admin-api.yaml#/components/schemas/Error" }
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
            "404":
                description: No flag with this id.
                content:
                    application/json:
                        schema: { $ref: "../admin-api.yaml#/components/schemas/Error" }
        x-access-policies: [Admin, Inventory]
        x-scopes: ["shipping:write", "admin:all"]

"/admin/dhl/reconcile":
    post:
        tags: [DHL]
        operationId: reconcileDHLInvoice
        summary: Reconcile an invoice against quoted rates
        description: |
            Reconciles an invoice by comparing each charge against the quoted shipment rate
            captured when the label was bought. Creates `DHLChargeFlag` rows for discrepancies.
            Idempotent — deletes existing flags for the invoice before recomputing.

            Flag reasons: `TrackingNotFound` | `NoQuotedRate` | `OverThreshold`.
        requestBody:
            required: true
            content:
                application/json:
                    schema:
                        type: object
                        required: [invoiceId]
                        properties:
                            invoiceId: { type: string }
                            threshold:
                                type: number
                                description: Discrepancy threshold; default `0` (flag any difference).
        responses:
            "200":
                description: Reconciliation summary.
                content:
                    application/json:
                        schema:
                            type: object
                            required: [invoiceId, invoiceNumber, chargesProcessed, flagsCreated]
                            properties:
                                invoiceId: { type: string }
                                invoiceNumber: { type: string }
                                chargesProcessed: { type: integer }
                                flagsCreated: { type: integer }
            "400":
                description: Missing `invoiceId`.
                content:
                    application/json:
                        schema: { $ref: "../admin-api.yaml#/components/schemas/Error" }
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
            "404":
                description: Invoice not found.
                content:
                    application/json:
                        schema: { $ref: "../admin-api.yaml#/components/schemas/Error" }
        x-access-policies: [Admin, Inventory]
        x-scopes: ["shipping:write", "admin:all"]

"/admin/dhl/all":
    delete:
        tags: [DHL]
        operationId: clearAllDHLData
        summary: Wipe every DHL invoice, charge, and flag
        description: |
            **Destructive and irreversible.** Deletes every DHL invoice, charge, and flag
            in a single transaction (flags → charges → invoices, rolled back on any
            failure). Intended for test resets and dev environments. Stricter auth than
            the rest of `/admin/dhl/*` — `Inventory` cannot call this.
        responses:
            "200":
                description: Wipe summary.
                content:
                    application/json:
                        schema:
                            type: object
                            required: [flagsDeleted, chargesDeleted, invoicesDeleted]
                            properties:
                                flagsDeleted: { type: integer }
                                chargesDeleted: { type: integer }
                                invoicesDeleted: { type: integer }
            "401": { $ref: "../admin-api.yaml#/components/responses/Unauthorized" }
            "403": { $ref: "../admin-api.yaml#/components/responses/Forbidden" }
        x-access-policies: [Admin]
        x-scopes: ["shipping:write", "admin:all"]
