import { beforeEach, describe, expect, it, vi } from "vitest";
import { POST } from "@/app/api/quotes/route";
import { GET as getQuote } from "@/app/api/quotes/[quote_id]/route";
import { GET as getHistory } from "@/app/api/quotes/history/route";
import { PUT as putMarkup } from "@/app/api/markup-configs/[customer_id]/route";

vi.mock("@/modules/quote/orchestrator", () => ({
  submitQuote: vi.fn(),
}));

vi.mock("@/lib/api/rate-limit", () => ({
  enforceRateLimits: vi.fn().mockResolvedValue(null),
}));

vi.mock("@/lib/prisma", () => ({
  prisma: {
    quoteRecord: {
      findFirst: vi.fn(),
      count: vi.fn(),
      findMany: vi.fn(),
    },
    markupConfig: { upsert: vi.fn() },
    auditLog: { create: vi.fn().mockResolvedValue({}) },
    alertLog: { create: vi.fn().mockResolvedValue({}) },
  },
}));

import { submitQuote } from "@/modules/quote/orchestrator";
import { prisma } from "@/lib/prisma";
import { resetServiceTokenCache } from "@/modules/auth/service-token";
import {
  MOTHERSHIP_DELIVERY_CONFIRMED,
  MOTHERSHIP_PICKUP_CONFIRMED,
} from "@/__tests__/fixtures/mothership-address";

const SERVICE_HEADERS = {
  "x-auth-type": "service",
  "x-customer-id": "CUST_001",
  "x-permissions": "pricing:markup:write",
};

const VALID_BODY = {
  request_id: "550e8400-e29b-41d4-a716-446655440000",
  customer_id: "CUST_001",
  pickup_address: {
    street: "1234 Warehouse Blvd",
    city: "Los Angeles",
    state: "CA",
    zip: "90001",
    place_id: "ChIJ_pickup",
    formatted_address: "1234 Warehouse Blvd, Los Angeles, CA 90001, USA",
    selected_from_suggestions: true,
    ...MOTHERSHIP_PICKUP_CONFIRMED,
  },
  delivery_address: {
    street: "5678 Distribution Dr",
    city: "Dallas",
    state: "TX",
    zip: "75201",
    place_id: "ChIJ_delivery",
    formatted_address: "5678 Distribution Dr, Dallas, TX 75201, USA",
    selected_from_suggestions: true,
    ...MOTHERSHIP_DELIVERY_CONFIRMED,
  },
  weight: { value: 500, unit: "lb" },
  dimensions: { length: 48, width: 40, height: 48, unit: "in" },
  pallet_count: 2,
  cargo_type: "general_freight",
};

beforeEach(() => {
  vi.clearAllMocks();
  resetServiceTokenCache();
  process.env.HOST_SERVICE_TOKENS = JSON.stringify({
    "demo-host-token": {
      customerId: "CUST_001",
      permissions: ["pricing:markup:write"],
    },
  });
});

describe("POST /api/quotes", () => {
  it("正常询价 → 200 + quote_id", async () => {
    vi.mocked(submitQuote).mockResolvedValue({
      quote_id: "QTE_001",
      status: "done",
      source_type: "cache",
    });

    const response = await POST(
      new Request("http://localhost/api/quotes", {
        method: "POST",
        headers: { "Content-Type": "application/json", ...SERVICE_HEADERS },
        body: JSON.stringify(VALID_BODY),
      }),
    );
    const json = await response.json();

    expect(response.status).toBe(200);
    expect(json.code).toBe(0);
    expect(json.data.quote_id).toBe("QTE_001");
    expect(json.data.source_type).toBe("cache");
  });

  it("customer_id 不匹配 → 403", async () => {
    const response = await POST(
      new Request("http://localhost/api/quotes", {
        method: "POST",
        headers: { "Content-Type": "application/json", ...SERVICE_HEADERS },
        body: JSON.stringify({ ...VALID_BODY, customer_id: "CUST_999" }),
      }),
    );
    expect(response.status).toBe(403);
  });
});

describe("GET /api/quotes/{quote_id}", () => {
  it("他人 quote_id → 403（TC-501）", async () => {
    vi.mocked(prisma.quoteRecord.findFirst).mockResolvedValue({
      quoteId: "QTE_B",
      customerId: "CUST_B",
      requestId: "req",
      status: "done",
      currency: "USD",
      isRealtime: true,
      sourceType: "cache",
      confidenceScore: null,
      validUntil: new Date(Date.now() + 60_000),
      quotesJson: [],
      errorCode: null,
      createdAt: new Date(),
      updatedAt: new Date(),
    } as never);

    const response = await getQuote(
      new Request("http://localhost/api/quotes/QTE_B", {
        headers: SERVICE_HEADERS,
      }),
      { params: Promise.resolve({ quote_id: "QTE_B" }) },
    );
    expect(response.status).toBe(403);
  });

  it("不存在 → 404", async () => {
    vi.mocked(prisma.quoteRecord.findFirst).mockResolvedValue(null);

    const response = await getQuote(
      new Request("http://localhost/api/quotes/QTE_X", {
        headers: SERVICE_HEADERS,
      }),
      { params: Promise.resolve({ quote_id: "QTE_X" }) },
    );
    expect(response.status).toBe(404);
  });
});

describe("GET /api/quotes/history", () => {
  it("缺 page/size → 400（TC-506）", async () => {
    const response = await getHistory(
      new Request("http://localhost/api/quotes/history", {
        headers: SERVICE_HEADERS,
      }),
    );
    expect(response.status).toBe(400);
  });
});

describe("PUT /api/markup-configs/{customer_id}", () => {
  it("markup=30.1 → 400（TC-505）", async () => {
    const response = await putMarkup(
      new Request("http://localhost/api/markup-configs/CUST_001", {
        method: "PUT",
        headers: { "Content-Type": "application/json", ...SERVICE_HEADERS },
        body: JSON.stringify({ markup_percent: 30.1, operator_id: "op1" }),
      }),
      { params: Promise.resolve({ customer_id: "CUST_001" }) },
    );
    expect(response.status).toBe(400);
  });

  it("无 pricing:markup:write → 403（TC-502）", async () => {
    const response = await putMarkup(
      new Request("http://localhost/api/markup-configs/CUST_001", {
        method: "PUT",
        headers: {
          "Content-Type": "application/json",
          "x-auth-type": "service",
          "x-customer-id": "CUST_001",
          "x-permissions": "",
        },
        body: JSON.stringify({ markup_percent: 10, operator_id: "op1" }),
      }),
      { params: Promise.resolve({ customer_id: "CUST_001" }) },
    );
    expect(response.status).toBe(403);
  });
});
