import { describe, it, expect } from "vitest";
import {
  ApplicationError,
  ValidationError,
  UnauthorizedError,
  ChildNotBoundError,
  NotFoundError,
  ConflictError,
  BusinessError,
  BadGatewayError,
  GatewayTimeoutError,
  ServiceUnavailableError,
  InternalError,
} from "../../src/shared/errors/application-error.js";

describe("ApplicationError 体系", () => {
  describe("ValidationError", () => {
    it("statusCode 为 400", () => {
      const err = new ValidationError("参数错误");
      expect(err.statusCode).toBe(400);
      expect(err.code).toBe("BFF_PARENT_VALIDATION_ERROR");
      expect(err.type).toBe("validation");
      expect(err.message).toBe("参数错误");
    });

    it("携带 details", () => {
      const err = new ValidationError("参数错误", { field: "name" });
      expect(err.details).toEqual({ field: "name" });
    });
  });

  describe("UnauthorizedError", () => {
    it("statusCode 为 401", () => {
      const err = new UnauthorizedError("未授权");
      expect(err.statusCode).toBe(401);
      expect(err.code).toBe("BFF_PARENT_UNAUTHORIZED");
    });
  });

  describe("ChildNotBoundError", () => {
    it("statusCode 为 403", () => {
      const err = new ChildNotBoundError("parent-001", "student-999", [
        "student-001",
        "student-002",
      ]);
      expect(err.statusCode).toBe(403);
      expect(err.code).toBe("BFF_PARENT_CHILD_NOT_BOUND");
      expect(err.type).toBe("child_not_bound");
      expect(err.details).toEqual({
        parentId: "parent-001",
        requestedChildId: "student-999",
        boundChildren: ["student-001", "student-002"],
      });
    });

    it("message 包含 parentId 和 childId", () => {
      const err = new ChildNotBoundError("parent-001", "student-999", []);
      expect(err.message).toContain("student-999");
      expect(err.message).toContain("parent-001");
    });
  });

  describe("NotFoundError", () => {
    it("statusCode 为 404", () => {
      const err = new NotFoundError("Parent", "parent-999");
      expect(err.statusCode).toBe(404);
      expect(err.code).toBe("BFF_PARENT_NOT_FOUND");
      expect(err.message).toContain("Parent");
      expect(err.message).toContain("parent-999");
    });
  });

  describe("ConflictError", () => {
    it("statusCode 为 409", () => {
      const err = new ConflictError("冲突");
      expect(err.statusCode).toBe(409);
      expect(err.code).toBe("BFF_PARENT_CONFLICT");
    });
  });

  describe("BusinessError", () => {
    it("statusCode 为 422", () => {
      const err = new BusinessError("业务错误");
      expect(err.statusCode).toBe(422);
      expect(err.code).toBe("BFF_PARENT_BUSINESS_ERROR");
    });
  });

  describe("BadGatewayError", () => {
    it("statusCode 为 502", () => {
      const err = new BadGatewayError("下游错误");
      expect(err.statusCode).toBe(502);
      expect(err.code).toBe("BFF_PARENT_BAD_GATEWAY");
    });
  });

  describe("GatewayTimeoutError", () => {
    it("statusCode 为 504", () => {
      const err = new GatewayTimeoutError("超时");
      expect(err.statusCode).toBe(504);
      expect(err.code).toBe("BFF_PARENT_GATEWAY_TIMEOUT");
    });
  });

  describe("ServiceUnavailableError", () => {
    it("statusCode 为 503", () => {
      const err = new ServiceUnavailableError("不可用");
      expect(err.statusCode).toBe(503);
      expect(err.code).toBe("BFF_PARENT_SERVICE_UNAVAILABLE");
    });
  });

  describe("InternalError", () => {
    it("statusCode 为 500", () => {
      const err = new InternalError("内部错误");
      expect(err.statusCode).toBe(500);
      expect(err.code).toBe("BFF_PARENT_INTERNAL_ERROR");
    });
  });

  describe("toJSON", () => {
    it("序列化为 ActionState 信封格式", () => {
      const err = new ValidationError("参数错误", { field: "name" });
      err.traceId = "trace-001";
      const json = err.toJSON();
      expect(json.success).toBe(false);
      // 从 unknown 转换：toJSON 返回 Record<string, unknown>
      const error = json.error as {
        code: string;
        message: string;
        details: unknown;
        traceId?: string;
      };
      expect(error.code).toBe("BFF_PARENT_VALIDATION_ERROR");
      expect(error.message).toBe("参数错误");
      expect(error.details).toEqual({ field: "name" });
      expect(error.traceId).toBe("trace-001");
    });

    it("无 traceId 时序列化正常", () => {
      const err = new NotFoundError("Child", "child-999");
      const json = err.toJSON();
      expect(json.success).toBe(false);
      // 从 unknown 转换：toJSON 返回 Record<string, unknown>
      const error = json.error as { traceId?: string };
      expect(error.traceId).toBeUndefined();
    });
  });

  describe("继承关系", () => {
    it("所有错误继承自 ApplicationError", () => {
      const errors = [
        new ValidationError(""),
        new UnauthorizedError(""),
        new ChildNotBoundError("", "", []),
        new NotFoundError("", ""),
        new ConflictError(""),
        new BusinessError(""),
        new BadGatewayError(""),
        new GatewayTimeoutError(""),
        new ServiceUnavailableError(""),
        new InternalError(""),
      ];
      for (const err of errors) {
        expect(err).toBeInstanceOf(ApplicationError);
        expect(err).toBeInstanceOf(Error);
      }
    });

    it("name 属性为构造函数名", () => {
      expect(new ValidationError("").name).toBe("ValidationError");
      expect(new ChildNotBoundError("", "", []).name).toBe(
        "ChildNotBoundError",
      );
    });
  });
});
