const authSecurity = [{ SessionToken: [] }, { SecureSessionToken: [] }];
const adminSecurity = [{ SessionToken: [] }, { SecureSessionToken: [] }];

const jsonContent = (schema: unknown, example?: unknown) => ({
  "application/json": {
    schema,
    ...(example !== undefined ? { example } : {}),
  },
});

const requestBody = (schema: unknown, example?: unknown, required = true) => ({
  required,
  content: jsonContent(schema, example),
});

const jsonResponse = (description: string, schema: unknown, example?: unknown) => ({
  description,
  content: jsonContent(schema, example),
});

const errorResponse = (status: string, description: string, example?: string) => [
  status,
  jsonResponse(
    description,
    { $ref: "#/components/schemas/ErrorResponse" },
    example ? { error: example } : undefined
  ),
];

export const openApiSpec = {
  openapi: "3.0.3",
  info: {
    title: "Football Next API",
    version: "1.0.0",
    description:
      "مستندات Swagger/OpenAPI برای تمام APIهای پروژه Football Next. این مستندات بر اساس Routeهای فعلی پروژه تهیه شده و برای توسعه، تست و تحویل به فرانت/بک قابل استفاده است.",
  },
  servers: [
    {
      url: process.env.NEXTAUTH_URL ?? "http://localhost:3000",
      description: "Current app origin",
    },
  ],
  tags: [
    { name: "Auth", description: "ثبت‌نام، نشست و مسیرهای مرتبط با NextAuth" },
    { name: "User", description: "عملیات مرتبط با پروفایل و نشست کاربر" },
    { name: "Team", description: "ساخت و مدیریت تیم فانتزی کاربر" },
    { name: "Players", description: "دریافت و مدیریت بازیکنان" },
    { name: "Countries", description: "دریافت و مدیریت کشورها" },
    { name: "Matches", description: "دریافت و مدیریت بازی‌ها و آمار آن‌ها" },
    { name: "Rounds", description: "مدیریت دورها" },
    { name: "Gameweeks", description: "مدیریت هفته‌ها" },
    { name: "Leaderboard", description: "رتبه‌بندی تیم‌ها" },
    { name: "Upload", description: "آپلود فایل‌های تصویری" },
    { name: "Payment", description: "شروع و تایید پرداخت" },
    { name: "Quiz", description: "کوئیز روزانه و نتایج آن" },
    { name: "Golden Cards", description: "کارت‌های طلایی کاربر" },
    { name: "Admin", description: "APIهای ویژه ادمین" },
  ],
  components: {
    securitySchemes: {
      SessionToken: {
        type: "apiKey",
        in: "cookie",
        name: "next-auth.session-token",
        description: "توکن سشن NextAuth در محیط عادی",
      },
      SecureSessionToken: {
        type: "apiKey",
        in: "cookie",
        name: "__Secure-next-auth.session-token",
        description: "توکن سشن NextAuth در محیط HTTPS",
      },
    },
    schemas: {
      ErrorResponse: {
        type: "object",
        properties: {
          error: { type: "string", example: "Unauthorized" },
        },
        required: ["error"],
      },
      SuccessResponse: {
        type: "object",
        properties: {
          success: { type: "boolean", example: true },
        },
        required: ["success"],
      },
      Role: {
        type: "string",
        enum: ["USER", "ADMIN"],
      },
      Position: {
        type: "string",
        enum: ["GK", "DEF", "MID", "FWD"],
      },
      MatchStage: {
        type: "string",
        enum: ["GROUP", "ROUND_OF_16", "QUARTER_FINAL", "SEMI_FINAL", "THIRD_PLACE", "FINAL"],
      },
      MatchStatus: {
        type: "string",
        enum: ["SCHEDULED", "LIVE", "FINISHED"],
      },
      TeamStatus: {
        type: "string",
        enum: ["PENDING", "APPROVED", "REJECTED", "ACTIVE", "INACTIVE"],
      },
      GoldenCardStatus: {
        type: "string",
        enum: ["SEALED", "OPENED"],
      },
      EventType: {
        type: "string",
        enum: [
          "GOAL",
          "ASSIST",
          "YELLOW_CARD",
          "RED_CARD",
          "SECOND_YELLOW",
          "SUBSTITUTION_IN",
          "SUBSTITUTION_OUT",
          "INJURY_NO_SUB",
          "CLEAN_SHEET",
          "PENALTY_SAVED",
          "PENALTY_MISSED",
          "OWN_GOAL",
          "EXTRA_TIME_BONUS",
          "MOTM",
        ],
      },
      Group: {
        type: "object",
        properties: {
          id: { type: "string" },
          name: { type: "string" },
        },
      },
      Country: {
        type: "object",
        properties: {
          id: { type: "string" },
          name: { type: "string" },
          code: { type: "string" },
          flagUrl: { type: "string", nullable: true },
          flagImage: { type: "string", nullable: true },
          confederation: { type: "string", nullable: true },
          qualificationMethod: { type: "string", nullable: true },
          qualificationDate: { type: "string", nullable: true },
          participationHistory: { type: "string", nullable: true },
          bestResult: { type: "string", nullable: true },
          description: { type: "string", nullable: true },
          defaultFormation: { type: "string", example: "4-3-3" },
          defaultLineupPlayerIds: { type: "array", items: { type: "string" } },
          defaultCaptainId: { type: "string", nullable: true },
          groupId: { type: "string", nullable: true },
          isEliminated: { type: "boolean" },
          group: { $ref: "#/components/schemas/Group" },
        },
      },
      Player: {
        type: "object",
        properties: {
          id: { type: "string" },
          name: { type: "string" },
          image: { type: "string", nullable: true },
          position: { $ref: "#/components/schemas/Position" },
          countryId: { type: "string" },
          country: { $ref: "#/components/schemas/Country" },
          price: { type: "number", format: "float" },
          totalPoints: { type: "integer" },
          isActive: { type: "boolean" },
          isGoldenCardEligible: { type: "boolean" },
          createdAt: { type: "string", format: "date-time" },
          updatedAt: { type: "string", format: "date-time" },
        },
      },
      MatchLineupInput: {
        type: "object",
        properties: {
          countryId: { type: "string" },
          formation: { type: "string", example: "4-3-3" },
          playerIds: { type: "array", items: { type: "string" } },
        },
        required: ["countryId", "formation", "playerIds"],
      },
      MatchEvent: {
        type: "object",
        properties: {
          id: { type: "string" },
          matchId: { type: "string" },
          playerId: { type: "string" },
          type: { $ref: "#/components/schemas/EventType" },
          minute: { type: "integer", nullable: true },
          extraInfo: { type: "string", nullable: true },
          createdAt: { type: "string", format: "date-time" },
        },
      },
      PlayerMatchStat: {
        type: "object",
        properties: {
          id: { type: "string" },
          playerId: { type: "string" },
          matchId: { type: "string" },
          goals: { type: "integer" },
          assists: { type: "integer" },
          yellowCards: { type: "integer" },
          redCards: { type: "integer" },
          minutesPlayed: { type: "integer" },
          cleanSheet: { type: "boolean" },
          penaltySaved: { type: "integer" },
          penaltyMissed: { type: "integer" },
          ownGoals: { type: "integer" },
          isMotm: { type: "boolean" },
          extraTimeBonus: { type: "integer" },
          points: { type: "integer" },
        },
      },
      Match: {
        type: "object",
        properties: {
          id: { type: "string" },
          homeTeamId: { type: "string" },
          awayTeamId: { type: "string" },
          homeTeam: { $ref: "#/components/schemas/Country" },
          awayTeam: { $ref: "#/components/schemas/Country" },
          homeScore: { type: "integer", nullable: true },
          awayScore: { type: "integer", nullable: true },
          stage: { $ref: "#/components/schemas/MatchStage" },
          status: { $ref: "#/components/schemas/MatchStatus" },
          matchDate: { type: "string", format: "date-time" },
          matchDatePersian: { type: "string", nullable: true },
          stadium: { type: "string", nullable: true },
          city: { type: "string", nullable: true },
          referee: { type: "string", nullable: true },
          assistant1: { type: "string", nullable: true },
          assistant2: { type: "string", nullable: true },
          fourthOfficial: { type: "string", nullable: true },
          attendance: { type: "integer", nullable: true },
          weather: { type: "string", nullable: true },
          description: { type: "string", nullable: true },
          roundId: { type: "string", nullable: true },
          playerStats: {
            type: "array",
            items: { $ref: "#/components/schemas/PlayerMatchStat" },
          },
          createdAt: { type: "string", format: "date-time" },
        },
      },
      Round: {
        type: "object",
        properties: {
          id: { type: "string" },
          number: { type: "integer" },
          name: { type: "string" },
          isActive: { type: "boolean" },
          deadline: { type: "string", format: "date-time" },
          createdAt: { type: "string", format: "date-time" },
        },
      },
      Gameweek: {
        type: "object",
        properties: {
          id: { type: "string" },
          number: { type: "integer" },
          name: { type: "string" },
          isActive: { type: "boolean" },
          deadline: { type: "string", format: "date-time" },
          createdAt: { type: "string", format: "date-time" },
        },
      },
      TeamPlayer: {
        type: "object",
        properties: {
          teamId: { type: "string" },
          playerId: { type: "string" },
          player: { $ref: "#/components/schemas/Player" },
          isCaptain: { type: "boolean" },
          isViceCaptain: { type: "boolean" },
          isBench: { type: "boolean" },
          positionIndex: { type: "integer" },
        },
      },
      Team: {
        type: "object",
        properties: {
          id: { type: "string" },
          name: { type: "string" },
          userId: { type: "string" },
          budget: { type: "number", format: "float" },
          totalPoints: { type: "integer" },
          formation: { type: "string" },
          status: { $ref: "#/components/schemas/TeamStatus" },
          createdAt: { type: "string", format: "date-time" },
          players: {
            type: "array",
            items: { $ref: "#/components/schemas/TeamPlayer" },
          },
        },
      },
      LeaderboardEntry: {
        type: "object",
        properties: {
          rank: { type: "integer" },
          teamName: { type: "string" },
          userName: { type: "string" },
          totalPoints: { type: "integer" },
          budget: { type: "number", format: "float" },
        },
      },
      PaymentRequestPayload: {
        type: "object",
        properties: {
          packageId: { type: "string" },
        },
        required: ["packageId"],
      },
      PaymentRequestResponse: {
        type: "object",
        properties: {
          paymentUrl: { type: "string", format: "uri" },
        },
      },
      UploadPlayerImageResponse: {
        type: "object",
        properties: {
          success: { type: "boolean" },
          fileName: { type: "string" },
          url: { type: "string" },
        },
      },
      SessionInfo: {
        type: "object",
        properties: {
          user: {
            type: "object",
            properties: {
              name: { type: "string", nullable: true },
              email: { type: "string", nullable: true },
              image: { type: "string", nullable: true },
              role: { $ref: "#/components/schemas/Role" },
              id: { type: "string" },
            },
          },
          expires: { type: "string", format: "date-time" },
        },
      },
      DailyQuizQuestionPublic: {
        type: "object",
        properties: {
          id: { type: "string" },
          questionText: { type: "string" },
          options: { type: "array", items: { type: "string" } },
          order: { type: "integer" },
        },
      },
      DailyQuiz: {
        type: "object",
        properties: {
          id: { type: "string" },
          date: { type: "string", format: "date" },
          windowStart: { type: "string", format: "date-time" },
          windowEnd: { type: "string", format: "date-time" },
          goldWinnersCount: { type: "integer" },
          silverWinnersCount: { type: "integer" },
          bronzeWinnersCount: { type: "integer" },
          isProcessed: { type: "boolean" },
          createdAt: { type: "string", format: "date-time" },
          isActive: { type: "boolean" },
          questions: {
            type: "array",
            items: { $ref: "#/components/schemas/DailyQuizQuestionPublic" },
          },
        },
      },
      GoldenCard: {
        type: "object",
        properties: {
          id: { type: "string" },
          userId: { type: "string" },
          playerId: { type: "string" },
          status: { $ref: "#/components/schemas/GoldenCardStatus" },
          acquiredDate: { type: "string", format: "date-time" },
          openedAt: { type: "string", format: "date-time", nullable: true },
          player: { $ref: "#/components/schemas/Player" },
        },
      },
      RegisterRequest: {
        type: "object",
        properties: {
          name: { type: "string", nullable: true },
          email: { type: "string", format: "email" },
          password: { type: "string", format: "password" },
        },
        required: ["email", "password"],
      },
      RegisterResponse: {
        type: "object",
        properties: {
          id: { type: "string" },
        },
      },
      CredentialsLoginRequest: {
        type: "object",
        properties: {
          email: { type: "string", format: "email" },
          password: { type: "string", format: "password" },
          redirect: { type: "boolean", default: false },
          callbackUrl: { type: "string", nullable: true },
        },
        required: ["email", "password"],
      },
      TeamCreateRequest: {
        type: "object",
        properties: {
          name: { type: "string" },
          formation: { type: "string", example: "4-3-3" },
        },
        required: ["name"],
      },
      TeamPlayerAddRequest: {
        type: "object",
        properties: {
          playerId: { type: "string" },
          isBench: { type: "boolean", default: false },
        },
        required: ["playerId"],
      },
      TeamPlayerRemoveRequest: {
        type: "object",
        properties: {
          playerId: { type: "string" },
        },
        required: ["playerId"],
      },
      TeamFormationRequest: {
        type: "object",
        properties: {
          formation: {
            type: "string",
            enum: ["4-3-3", "4-4-2", "4-5-1", "3-5-2", "3-4-3", "5-3-2", "5-4-1"],
          },
        },
        required: ["formation"],
      },
      TeamCaptainRequest: {
        type: "object",
        properties: {
          playerId: { type: "string" },
          type: { type: "string", enum: ["captain", "viceCaptain"] },
        },
        required: ["playerId", "type"],
      },
      ProfileUpdateRequest: {
        type: "object",
        properties: {
          name: { type: "string" },
        },
        required: ["name"],
      },
      ManualPlayerStatInput: {
        type: "object",
        properties: {
          playerId: { type: "string" },
          goals: { type: "integer" },
          assists: { type: "integer" },
          yellowCards: { type: "integer" },
          redCards: { type: "integer" },
          minutesPlayed: { type: "integer" },
          cleanSheet: { type: "boolean" },
        },
        required: ["playerId", "goals", "assists", "yellowCards", "redCards", "minutesPlayed", "cleanSheet"],
      },
      QuizSubmitRequest: {
        type: "object",
        properties: {
          quizId: { type: "string" },
          answers: { type: "array", items: { type: "integer" } },
        },
        required: ["quizId", "answers"],
      },
      AdminQuizCreateRequest: {
        type: "object",
        properties: {
          date: { type: "string", format: "date" },
          windowStart: { type: "string", format: "date-time" },
          windowEnd: { type: "string", format: "date-time" },
          goldWinnersCount: { type: "integer", default: 1 },
          silverWinnersCount: { type: "integer", default: 0 },
          bronzeWinnersCount: { type: "integer", default: 0 },
          questions: {
            type: "array",
            items: {
              type: "object",
              properties: {
                questionText: { type: "string" },
                options: { type: "array", items: { type: "string" } },
                correctAnswer: { type: "integer" },
              },
              required: ["questionText", "options", "correctAnswer"],
            },
          },
        },
        required: ["date", "windowStart", "windowEnd", "goldWinnersCount", "silverWinnersCount", "bronzeWinnersCount", "questions"],
      },
      AdminTeamStatusUpdateRequest: {
        type: "object",
        properties: {
          status: { $ref: "#/components/schemas/TeamStatus" },
        },
        required: ["status"],
      },
      ScoringRuleInput: {
        type: "object",
        properties: {
          position: { $ref: "#/components/schemas/Position" },
          eventType: { $ref: "#/components/schemas/EventType" },
          points: { type: "integer" },
        },
        required: ["position", "eventType", "points"],
      },
      MatchEventCreateRequest: {
        type: "object",
        properties: {
          playerId: { type: "string" },
          type: { $ref: "#/components/schemas/EventType" },
          minute: { type: "integer", nullable: true },
          extraInfo: { type: "string", nullable: true },
        },
        required: ["playerId", "type"],
      },
    },
  },
  paths: {
    "/api/auth/register": {
      post: {
        tags: ["Auth"],
        summary: "ثبت‌نام کاربر جدید",
        requestBody: requestBody(
          { $ref: "#/components/schemas/RegisterRequest" },
          { name: "Ali", email: "ali@example.com", password: "123456" }
        ),
        responses: Object.fromEntries([
          ["201", jsonResponse("کاربر ساخته شد", { $ref: "#/components/schemas/RegisterResponse" }, { id: "clx123" })],
          errorResponse("400", "ورودی نامعتبر", "این ایمیل قبلاً ثبت شده"),
        ]),
      },
    },
    "/api/auth/callback/credentials": {
      post: {
        tags: ["Auth"],
        summary: "ورود با ایمیل و رمز عبور",
        description:
          "مسیر استاندارد NextAuth برای ورود. در فرانت معمولاً از `signIn('credentials')` استفاده می‌شود. در Swagger برای تست بهتر است از همان مرورگری استفاده شود که Session Cookie را نگه می‌دارد.",
        requestBody: requestBody(
          { $ref: "#/components/schemas/CredentialsLoginRequest" },
          { email: "admin@example.com", password: "123456", redirect: false }
        ),
        responses: {
          "200": {
            description: "ورود موفق یا پاسخ استاندارد NextAuth",
            content: {
              "application/json": {
                schema: {
                  type: "object",
                  additionalProperties: true,
                },
              },
            },
          },
        },
      },
    },
    "/api/auth/session": {
      get: {
        tags: ["Auth"],
        summary: "دریافت سشن جاری",
        responses: {
          "200": jsonResponse(
            "اطلاعات نشست",
            {
              oneOf: [{ $ref: "#/components/schemas/SessionInfo" }, { type: "null" }],
            }
          ),
        },
      },
    },
    "/api/auth/csrf": {
      get: {
        tags: ["Auth"],
        summary: "دریافت CSRF Token برای NextAuth",
        responses: {
          "200": jsonResponse(
            "توکن CSRF",
            {
              type: "object",
              properties: {
                csrfToken: { type: "string" },
              },
            }
          ),
        },
      },
    },
    "/api/auth/signout": {
      post: {
        tags: ["Auth"],
        summary: "خروج کاربر",
        security: authSecurity,
        responses: {
          "200": {
            description: "خروج موفق",
          },
        },
      },
    },
    "/api/user/profile": {
      put: {
        tags: ["User"],
        summary: "ویرایش نام کاربر",
        security: authSecurity,
        requestBody: requestBody(
          { $ref: "#/components/schemas/ProfileUpdateRequest" },
          { name: "Ali Rezaei" }
        ),
        responses: Object.fromEntries([
          ["200", jsonResponse("پروفایل به‌روزرسانی شد", { type: "object", properties: { name: { type: "string", nullable: true } } })],
          errorResponse("401", "نیازمند ورود", "Unauthorized"),
        ]),
      },
    },
    "/api/test-session": {
      get: {
        tags: ["User"],
        summary: "بررسی سشن و وضعیت کاربر در دیتابیس",
        security: authSecurity,
        responses: Object.fromEntries([
          [
            "200",
            jsonResponse("وضعیت سشن", {
              type: "object",
              additionalProperties: true,
            }),
          ],
          errorResponse("401", "بدون سشن", "No session"),
        ]),
      },
    },
    "/api/team": {
      get: {
        tags: ["Team"],
        summary: "دریافت تیم کاربر جاری",
        security: authSecurity,
        responses: Object.fromEntries([
          ["200", jsonResponse("تیم کاربر", { oneOf: [{ $ref: "#/components/schemas/Team" }, { type: "null" }] })],
          errorResponse("401", "نیازمند ورود", "Unauthorized"),
        ]),
      },
      post: {
        tags: ["Team"],
        summary: "ساخت تیم جدید برای کاربر",
        security: authSecurity,
        requestBody: requestBody(
          { $ref: "#/components/schemas/TeamCreateRequest" },
          { name: "Dream FC", formation: "4-3-3" }
        ),
        responses: Object.fromEntries([
          ["201", jsonResponse("تیم ساخته شد", { $ref: "#/components/schemas/Team" })],
          errorResponse("400", "خطای اعتبارسنجی", "Team already exists"),
          errorResponse("401", "نیازمند ورود", "Unauthorized"),
          errorResponse("404", "کاربر پیدا نشد", "User not found"),
        ]),
      },
    },
    "/api/team/players": {
      post: {
        tags: ["Team"],
        summary: "افزودن بازیکن به تیم",
        security: authSecurity,
        requestBody: requestBody(
          { $ref: "#/components/schemas/TeamPlayerAddRequest" },
          { playerId: "player_123", isBench: false }
        ),
        responses: Object.fromEntries([
          ["201", jsonResponse("بازیکن به تیم اضافه شد", { $ref: "#/components/schemas/TeamPlayer" })],
          errorResponse("400", "خطای اعتبارسنجی", "بودجه کافی نیست"),
          errorResponse("401", "نیازمند ورود", "Unauthorized"),
          errorResponse("404", "بازیکن پیدا نشد", "بازیکن پیدا نشد"),
        ]),
      },
      delete: {
        tags: ["Team"],
        summary: "حذف بازیکن از تیم",
        security: authSecurity,
        requestBody: requestBody(
          { $ref: "#/components/schemas/TeamPlayerRemoveRequest" },
          { playerId: "player_123" }
        ),
        responses: Object.fromEntries([
          ["200", jsonResponse("بازیکن حذف شد", { $ref: "#/components/schemas/SuccessResponse" })],
          errorResponse("401", "نیازمند ورود", "Unauthorized"),
          errorResponse("404", "تیم پیدا نشد", "تیم پیدا نشد"),
        ]),
      },
    },
    "/api/team/formation": {
      put: {
        tags: ["Team"],
        summary: "تغییر ترکیب تیم",
        security: authSecurity,
        requestBody: requestBody(
          { $ref: "#/components/schemas/TeamFormationRequest" },
          { formation: "4-4-2" }
        ),
        responses: Object.fromEntries([
          ["200", jsonResponse("ترکیب به‌روزرسانی شد", { $ref: "#/components/schemas/Team" })],
          errorResponse("400", "ترکیب نامعتبر یا ناسازگار", "ترکیب نامعتبر"),
          errorResponse("401", "نیازمند ورود", "Unauthorized"),
          errorResponse("404", "تیم پیدا نشد", "تیم پیدا نشد"),
        ]),
      },
    },
    "/api/team/captain": {
      put: {
        tags: ["Team"],
        summary: "تعیین کاپیتان یا نایب کاپیتان",
        security: authSecurity,
        requestBody: requestBody(
          { $ref: "#/components/schemas/TeamCaptainRequest" },
          { playerId: "player_123", type: "captain" }
        ),
        responses: Object.fromEntries([
          ["200", jsonResponse("بروزرسانی موفق", { $ref: "#/components/schemas/SuccessResponse" })],
          errorResponse("401", "نیازمند ورود", "Unauthorized"),
          errorResponse("404", "تیم پیدا نشد", "تیم پیدا نشد"),
        ]),
      },
    },
    "/api/team/submit": {
      post: {
        tags: ["Team"],
        summary: "ثبت نهایی تیم",
        security: authSecurity,
        responses: Object.fromEntries([
          ["200", jsonResponse("تیم نهایی شد", { $ref: "#/components/schemas/Team" })],
          errorResponse("400", "ترکیب تیم نامعتبر است", "تیم باید دقیقاً ۱۵ بازیکن داشته باشد"),
          errorResponse("401", "نیازمند ورود", "Unauthorized"),
          errorResponse("404", "تیم پیدا نشد", "تیم پیدا نشد"),
        ]),
      },
    },
    "/api/players": {
      get: {
        tags: ["Players"],
        summary: "لیست بازیکنان",
        parameters: [
          { in: "query", name: "position", schema: { $ref: "#/components/schemas/Position" }, required: false },
          { in: "query", name: "countryId", schema: { type: "string" }, required: false },
        ],
        responses: {
          "200": jsonResponse("لیست بازیکنان", { type: "array", items: { $ref: "#/components/schemas/Player" } }),
        },
      },
      post: {
        tags: ["Players"],
        summary: "ایجاد بازیکن جدید",
        security: adminSecurity,
        requestBody: requestBody(
          {
            type: "object",
            additionalProperties: true,
            properties: {
              name: { type: "string" },
              position: { $ref: "#/components/schemas/Position" },
              countryId: { type: "string" },
              price: { type: "number" },
              image: { type: "string", nullable: true },
            },
          },
          { name: "Lionel Messi", position: "FWD", countryId: "country_1", price: 12.5 }
        ),
        responses: Object.fromEntries([
          ["201", jsonResponse("بازیکن ایجاد شد", { $ref: "#/components/schemas/Player" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/players/{id}": {
      put: {
        tags: ["Players"],
        summary: "ویرایش بازیکن",
        security: adminSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        requestBody: requestBody(
          {
            type: "object",
            additionalProperties: true,
          },
          { price: 11.5, isActive: true }
        ),
        responses: Object.fromEntries([
          ["200", jsonResponse("بازیکن به‌روزرسانی شد", { $ref: "#/components/schemas/Player" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
      delete: {
        tags: ["Players"],
        summary: "حذف بازیکن",
        security: adminSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        responses: Object.fromEntries([
          ["200", jsonResponse("بازیکن حذف شد", { $ref: "#/components/schemas/SuccessResponse" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/admin/players/{id}/golden-toggle": {
      patch: {
        tags: ["Admin", "Golden Cards"],
        summary: "فعال/غیرفعال کردن صلاحیت Golden Card برای بازیکن",
        security: adminSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        responses: Object.fromEntries([
          [
            "200",
            jsonResponse("وضعیت تغییر کرد", {
              type: "object",
              properties: {
                isGoldenCardEligible: { type: "boolean" },
              },
            }),
          ],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
          errorResponse("404", "بازیکن پیدا نشد", "Player not found"),
        ]),
      },
    },
    "/api/countries": {
      get: {
        tags: ["Countries"],
        summary: "لیست کشورها",
        responses: {
          "200": jsonResponse("لیست کشورها", { type: "array", items: { $ref: "#/components/schemas/Country" } }),
        },
      },
      post: {
        tags: ["Countries"],
        summary: "ایجاد کشور جدید",
        security: adminSecurity,
        requestBody: requestBody(
          {
            type: "object",
            additionalProperties: true,
            properties: {
              name: { type: "string" },
              code: { type: "string" },
              defaultFormation: { type: "string" },
            },
          },
          { name: "Argentina", code: "ARG", defaultFormation: "4-3-3" }
        ),
        responses: Object.fromEntries([
          ["201", jsonResponse("کشور ایجاد شد", { $ref: "#/components/schemas/Country" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/countries/{id}": {
      put: {
        tags: ["Countries"],
        summary: "ویرایش کشور",
        security: adminSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        requestBody: requestBody({ type: "object", additionalProperties: true }, { isEliminated: false }),
        responses: Object.fromEntries([
          ["200", jsonResponse("کشور به‌روزرسانی شد", { $ref: "#/components/schemas/Country" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
      delete: {
        tags: ["Countries"],
        summary: "حذف کشور",
        security: adminSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        responses: Object.fromEntries([
          ["200", jsonResponse("کشور حذف شد", { $ref: "#/components/schemas/SuccessResponse" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/matches": {
      get: {
        tags: ["Matches"],
        summary: "لیست بازی‌ها",
        responses: {
          "200": jsonResponse("لیست بازی‌ها", { type: "array", items: { $ref: "#/components/schemas/Match" } }),
        },
      },
      post: {
        tags: ["Matches"],
        summary: "ایجاد بازی جدید",
        security: adminSecurity,
        requestBody: requestBody(
          {
            type: "object",
            additionalProperties: true,
            properties: {
              homeTeamId: { type: "string" },
              awayTeamId: { type: "string" },
              stage: { $ref: "#/components/schemas/MatchStage" },
              status: { $ref: "#/components/schemas/MatchStatus" },
              matchDate: { type: "string", format: "date-time" },
              roundId: { type: "string", nullable: true },
            },
          },
          {
            homeTeamId: "country_1",
            awayTeamId: "country_2",
            stage: "GROUP",
            status: "SCHEDULED",
            matchDate: "2026-06-10T19:00:00.000Z",
          }
        ),
        responses: Object.fromEntries([
          ["201", jsonResponse("بازی ایجاد شد", { $ref: "#/components/schemas/Match" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/matches/{id}": {
      get: {
        tags: ["Matches"],
        summary: "جزئیات یک بازی",
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        responses: Object.fromEntries([
          ["200", jsonResponse("جزئیات بازی", { $ref: "#/components/schemas/Match" })],
          errorResponse("404", "بازی پیدا نشد", "Not found"),
        ]),
      },
      put: {
        tags: ["Matches"],
        summary: "ویرایش بازی",
        security: adminSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        requestBody: requestBody({ type: "object", additionalProperties: true }, { status: "LIVE", homeScore: 1, awayScore: 0 }),
        responses: Object.fromEntries([
          ["200", jsonResponse("بازی به‌روزرسانی شد", { $ref: "#/components/schemas/Match" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
      delete: {
        tags: ["Matches"],
        summary: "حذف بازی",
        security: adminSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        responses: Object.fromEntries([
          ["200", jsonResponse("بازی حذف شد", { $ref: "#/components/schemas/SuccessResponse" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/matches/{id}/stats": {
      post: {
        tags: ["Matches"],
        summary: "ثبت دستی آمار بازیکنان یک بازی",
        description: "این مسیر برای ثبت مستقیم آمار بازیکنان و محاسبه امتیاز آن‌ها استفاده می‌شود.",
        security: adminSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        requestBody: requestBody(
          {
            type: "array",
            items: { $ref: "#/components/schemas/ManualPlayerStatInput" },
          },
          [
            {
              playerId: "player_1",
              goals: 1,
              assists: 0,
              yellowCards: 0,
              redCards: 0,
              minutesPlayed: 90,
              cleanSheet: false,
            },
          ]
        ),
        responses: Object.fromEntries([
          ["200", jsonResponse("آمار ذخیره شد", { type: "array", items: { $ref: "#/components/schemas/PlayerMatchStat" } })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/admin/matches/{id}/lineup": {
      post: {
        tags: ["Admin", "Matches"],
        summary: "ثبت ترکیب دو تیم برای یک بازی",
        security: adminSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        requestBody: requestBody(
          {
            type: "array",
            items: { $ref: "#/components/schemas/MatchLineupInput" },
          },
          [
            { countryId: "country_1", formation: "4-3-3", playerIds: ["p1", "p2"] },
            { countryId: "country_2", formation: "4-4-2", playerIds: ["p3", "p4"] },
          ]
        ),
        responses: Object.fromEntries([
          ["200", jsonResponse("ترکیب‌ها ذخیره شدند", { $ref: "#/components/schemas/SuccessResponse" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/admin/matches/{id}/events": {
      post: {
        tags: ["Admin", "Matches"],
        summary: "ثبت رویداد بازی",
        security: adminSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        requestBody: requestBody(
          { $ref: "#/components/schemas/MatchEventCreateRequest" },
          { playerId: "player_1", type: "GOAL", minute: 35, extraInfo: "Right foot" }
        ),
        responses: Object.fromEntries([
          ["201", jsonResponse("رویداد ذخیره شد", { $ref: "#/components/schemas/MatchEvent" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/admin/matches/{id}/events/{eventId}": {
      delete: {
        tags: ["Admin", "Matches"],
        summary: "حذف رویداد بازی",
        security: adminSecurity,
        parameters: [
          { in: "path", name: "id", required: true, schema: { type: "string" } },
          { in: "path", name: "eventId", required: true, schema: { type: "string" } },
        ],
        responses: Object.fromEntries([
          ["200", jsonResponse("رویداد حذف شد", { $ref: "#/components/schemas/SuccessResponse" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/admin/matches/{id}/calc-points": {
      post: {
        tags: ["Admin", "Matches"],
        summary: "محاسبه امتیاز بازیکنان و تیم‌ها از روی رویدادهای ثبت‌شده",
        security: adminSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        responses: Object.fromEntries([
          [
            "200",
            jsonResponse("محاسبه انجام شد", {
              type: "object",
              properties: {
                calculated: { type: "integer" },
              },
            }),
          ],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/rounds": {
      get: {
        tags: ["Rounds"],
        summary: "لیست دورها",
        responses: {
          "200": jsonResponse("لیست دورها", { type: "array", items: { $ref: "#/components/schemas/Round" } }),
        },
      },
      post: {
        tags: ["Rounds"],
        summary: "ایجاد دور جدید",
        security: adminSecurity,
        requestBody: requestBody(
          {
            type: "object",
            properties: {
              number: { type: "integer" },
              name: { type: "string" },
              deadline: { type: "string", format: "date-time" },
            },
            required: ["number", "name", "deadline"],
          },
          { number: 1, name: "Round 1", deadline: "2026-06-10T12:00:00.000Z" }
        ),
        responses: Object.fromEntries([
          ["201", jsonResponse("دور ایجاد شد", { $ref: "#/components/schemas/Round" })],
          errorResponse("400", "شماره دور تکراری است", "این شماره دور قبلاً ثبت شده"),
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
      put: {
        tags: ["Rounds"],
        summary: "ویرایش دور",
        security: adminSecurity,
        requestBody: requestBody(
          {
            type: "object",
            properties: {
              id: { type: "string" },
              number: { type: "integer" },
              name: { type: "string" },
              deadline: { type: "string", format: "date-time" },
            },
            required: ["id", "number", "name", "deadline"],
          }
        ),
        responses: Object.fromEntries([
          ["200", jsonResponse("دور به‌روزرسانی شد", { $ref: "#/components/schemas/Round" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
      delete: {
        tags: ["Rounds"],
        summary: "حذف دور",
        security: adminSecurity,
        requestBody: requestBody(
          {
            type: "object",
            properties: {
              id: { type: "string" },
            },
            required: ["id"],
          },
          { id: "round_1" }
        ),
        responses: Object.fromEntries([
          ["200", jsonResponse("دور حذف شد", { $ref: "#/components/schemas/SuccessResponse" })],
          errorResponse("400", "این دور دارای بازی است", "این دور دارای بازی است و قابل حذف نیست"),
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/rounds/{id}/activate": {
      post: {
        tags: ["Rounds"],
        summary: "فعال/غیرفعال کردن یک دور",
        security: adminSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        responses: Object.fromEntries([
          ["200", jsonResponse("وضعیت دور تغییر کرد", { $ref: "#/components/schemas/Round" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
          errorResponse("404", "دور پیدا نشد", "Round not found"),
        ]),
      },
    },
    "/api/gameweeks": {
      get: {
        tags: ["Gameweeks"],
        summary: "لیست هفته‌ها",
        responses: {
          "200": jsonResponse("لیست هفته‌ها", { type: "array", items: { $ref: "#/components/schemas/Gameweek" } }),
        },
      },
      post: {
        tags: ["Gameweeks"],
        summary: "ایجاد هفته جدید",
        security: adminSecurity,
        requestBody: requestBody(
          {
            type: "object",
            additionalProperties: true,
            properties: {
              number: { type: "integer" },
              name: { type: "string" },
              deadline: { type: "string", format: "date-time" },
            },
          },
          { number: 1, name: "Gameweek 1", deadline: "2026-06-10T12:00:00.000Z" }
        ),
        responses: Object.fromEntries([
          ["201", jsonResponse("هفته ایجاد شد", { $ref: "#/components/schemas/Gameweek" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/gameweeks/{id}/activate": {
      post: {
        tags: ["Gameweeks"],
        summary: "فعال کردن یک هفته",
        security: adminSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        responses: Object.fromEntries([
          ["200", jsonResponse("هفته فعال شد", { $ref: "#/components/schemas/Gameweek" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/leaderboard": {
      get: {
        tags: ["Leaderboard"],
        summary: "دریافت جدول رتبه‌بندی",
        responses: {
          "200": jsonResponse(
            "لیست 50 تیم برتر",
            { type: "array", items: { $ref: "#/components/schemas/LeaderboardEntry" } }
          ),
        },
      },
    },
    "/api/upload/player-image": {
      post: {
        tags: ["Upload"],
        summary: "آپلود تصویر بازیکن",
        requestBody: {
          required: true,
          content: {
            "multipart/form-data": {
              schema: {
                type: "object",
                properties: {
                  file: {
                    type: "string",
                    format: "binary",
                  },
                },
                required: ["file"],
              },
            },
          },
        },
        responses: Object.fromEntries([
          ["200", jsonResponse("فایل آپلود شد", { $ref: "#/components/schemas/UploadPlayerImageResponse" })],
          errorResponse("400", "فایل نامعتبر", "فایلی انتخاب نشده است"),
          errorResponse("500", "خطای داخلی سرور", "خطا در آپلود فایل"),
        ]),
      },
    },
    "/api/payment/request": {
      post: {
        tags: ["Payment"],
        summary: "ساخت درخواست پرداخت زرین‌پال",
        security: authSecurity,
        requestBody: requestBody(
          { $ref: "#/components/schemas/PaymentRequestPayload" },
          { packageId: "pkg_123" }
        ),
        responses: Object.fromEntries([
          ["200", jsonResponse("آدرس پرداخت ایجاد شد", { $ref: "#/components/schemas/PaymentRequestResponse" })],
          errorResponse("400", "خطا در ساخت پرداخت", "خطا در اتصال به درگاه"),
          errorResponse("401", "نیازمند ورود", "Unauthorized"),
          errorResponse("404", "پکیج پیدا نشد", "پکیج پیدا نشد"),
        ]),
      },
    },
    "/api/payment/verify": {
      get: {
        tags: ["Payment"],
        summary: "تایید پرداخت و ریدایرکت به فروشگاه",
        description: "این Endpoint توسط زرین‌پال فراخوانی می‌شود و در نهایت کاربر را به `/shop` با query string مناسب منتقل می‌کند.",
        parameters: [
          { in: "query", name: "Authority", required: false, schema: { type: "string" } },
          { in: "query", name: "Status", required: false, schema: { type: "string", example: "OK" } },
        ],
        responses: {
          "307": {
            description: "ریدایرکت به /shop با وضعیت success, failed, cancelled یا error",
          },
        },
      },
    },
    "/api/quiz": {
      get: {
        tags: ["Quiz"],
        summary: "دریافت کوئیز روز جاری",
        responses: {
          "200": jsonResponse(
            "کوئیز روز یا null",
            {
              oneOf: [{ $ref: "#/components/schemas/DailyQuiz" }, { type: "null" }],
            }
          ),
        },
      },
    },
    "/api/quiz/submit": {
      post: {
        tags: ["Quiz"],
        summary: "ارسال پاسخ‌های کوئیز",
        security: authSecurity,
        requestBody: requestBody(
          { $ref: "#/components/schemas/QuizSubmitRequest" },
          { quizId: "quiz_123", answers: [1, 2, 0] }
        ),
        responses: Object.fromEntries([
          [
            "200",
            jsonResponse("نتیجه ثبت شد", {
              type: "object",
              properties: {
                score: { type: "integer" },
                correct: { type: "integer" },
                total: { type: "integer" },
                submission: { type: "object", additionalProperties: true },
              },
            }),
          ],
          errorResponse("400", "خطای ارسال یا خارج از بازه", "قبلاً شرکت کرده‌اید"),
          errorResponse("401", "نیازمند ورود", "Unauthorized"),
          errorResponse("404", "کوئیز پیدا نشد", "Quiz not found"),
        ]),
      },
    },
    "/api/quiz/my-results": {
      get: {
        tags: ["Quiz"],
        summary: "دریافت نتایج کوئیزهای کاربر",
        security: authSecurity,
        responses: Object.fromEntries([
          ["200", jsonResponse("نتایج کاربر", { type: "array", items: { type: "object", additionalProperties: true } })],
          errorResponse("401", "نیازمند ورود", "Unauthorized"),
        ]),
      },
    },
    "/api/admin/quiz": {
      get: {
        tags: ["Admin", "Quiz"],
        summary: "لیست تمام کوئیزها برای ادمین",
        security: adminSecurity,
        responses: Object.fromEntries([
          ["200", jsonResponse("لیست کوئیزها", { type: "array", items: { type: "object", additionalProperties: true } })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
      post: {
        tags: ["Admin", "Quiz"],
        summary: "ایجاد کوئیز جدید",
        security: adminSecurity,
        requestBody: requestBody(
          { $ref: "#/components/schemas/AdminQuizCreateRequest" },
          {
            date: "2026-06-10",
            windowStart: "2026-06-10T08:00:00.000Z",
            windowEnd: "2026-06-10T20:00:00.000Z",
            goldWinnersCount: 1,
            silverWinnersCount: 2,
            bronzeWinnersCount: 0,
            questions: [
              {
                questionText: "برنده بازی اول چه تیمی است؟",
                options: ["A", "B", "C", "D"],
                correctAnswer: 1,
              },
            ],
          }
        ),
        responses: Object.fromEntries([
          ["201", jsonResponse("کوئیز ایجاد شد", { type: "object", additionalProperties: true })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/admin/quiz/{id}/lottery": {
      post: {
        tags: ["Admin", "Quiz", "Golden Cards"],
        summary: "اجرای قرعه‌کشی برندگان کوئیز",
        security: adminSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        responses: Object.fromEntries([
          ["200", jsonResponse("خروجی قرعه‌کشی", { type: "object", additionalProperties: true })],
          errorResponse("400", "خطای قرعه‌کشی", "قرعه‌کشی قبلاً انجام شده"),
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
          errorResponse("404", "کوئیز پیدا نشد", "Quiz not found"),
        ]),
      },
    },
    "/api/golden-cards": {
      get: {
        tags: ["Golden Cards"],
        summary: "لیست کارت‌های طلایی کاربر جاری",
        security: authSecurity,
        responses: Object.fromEntries([
          ["200", jsonResponse("لیست کارت‌ها", { type: "array", items: { $ref: "#/components/schemas/GoldenCard" } })],
          errorResponse("401", "نیازمند ورود", "Unauthorized"),
        ]),
      },
    },
    "/api/golden-cards/{id}/reveal": {
      post: {
        tags: ["Golden Cards"],
        summary: "باز کردن کارت طلایی",
        security: authSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        responses: Object.fromEntries([
          ["200", jsonResponse("کارت باز شد", { $ref: "#/components/schemas/GoldenCard" })],
          errorResponse("400", "کارت قبلاً باز شده", "کارت قبلاً باز شده"),
          errorResponse("401", "نیازمند ورود", "Unauthorized"),
          errorResponse("403", "کارت متعلق به کاربر نیست", "Forbidden"),
          errorResponse("404", "کارت پیدا نشد", "Card not found"),
        ]),
      },
    },
    "/api/admin/teams": {
      get: {
        tags: ["Admin", "Team"],
        summary: "لیست تیم‌ها برای ادمین",
        security: adminSecurity,
        responses: Object.fromEntries([
          ["200", jsonResponse("لیست تیم‌ها", { type: "array", items: { type: "object", additionalProperties: true } })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/admin/teams/{id}": {
      put: {
        tags: ["Admin", "Team"],
        summary: "تغییر وضعیت یک تیم",
        security: adminSecurity,
        parameters: [{ in: "path", name: "id", required: true, schema: { type: "string" } }],
        requestBody: requestBody(
          { $ref: "#/components/schemas/AdminTeamStatusUpdateRequest" },
          { status: "APPROVED" }
        ),
        responses: Object.fromEntries([
          ["200", jsonResponse("وضعیت تیم به‌روزرسانی شد", { $ref: "#/components/schemas/Team" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
    "/api/admin/scoring": {
      put: {
        tags: ["Admin"],
        summary: "به‌روزرسانی قوانین امتیازدهی",
        security: adminSecurity,
        requestBody: requestBody(
          {
            type: "array",
            items: { $ref: "#/components/schemas/ScoringRuleInput" },
          },
          [{ position: "FWD", eventType: "GOAL", points: 4 }]
        ),
        responses: Object.fromEntries([
          ["200", jsonResponse("قوانین ذخیره شدند", { $ref: "#/components/schemas/SuccessResponse" })],
          errorResponse("401", "نیازمند دسترسی ادمین", "Unauthorized"),
        ]),
      },
    },
  },
};
