/**
 * Admin Access Control (Permission Groups) API
 *
 * GET /api/v1/admin/access-control
 *   List all permission groups with optional filtering.
 *
 *   Query Parameters:
 *     - organizationId?: string - Filter by organization ID
 *
 *   Response: { data: AdminPermissionGroup[], pagination: PaginationMeta }
 *
 * DELETE /api/v1/admin/access-control
 *   Delete permission groups scoped to an organization.
 *   Used when an enterprise plan churns to clean up access control data.
 *
 *   Query Parameters:
 *     - organizationId: string - Delete all permission groups for this organization
 *     - reason?: string - Reason recorded in audit log (default: "Enterprise plan churn cleanup")
 *
 *   Response: { success: true, deletedCount: number, membersRemoved: number }
 */

import { AuditAction, AuditResourceType, recordAudit } from '@sim/audit'
import { db } from '@sim/db'
import { organization, permissionGroup, permissionGroupMember, user } from '@sim/db/schema'
import { createLogger } from '@sim/logger'
import { count, eq, inArray, sql } from 'drizzle-orm'
import {
  type AdminV1PermissionGroup,
  adminV1DeleteAccessControlContract,
  adminV1ListAccessControlContract,
} from '@/lib/api/contracts/v1/admin'
import { parseRequest } from '@/lib/api/server'
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
import { withAdminAuth } from '@/app/api/v1/admin/middleware'
import {
  adminValidationErrorResponse,
  badRequestResponse,
  internalErrorResponse,
  singleResponse,
} from '@/app/api/v1/admin/responses'

const logger = createLogger('AdminAccessControlAPI')

export const GET = withRouteHandler(
  withAdminAuth(async (request) => {
    const parsed = await parseRequest(
      adminV1ListAccessControlContract,
      request,
      {},
      { validationErrorResponse: adminValidationErrorResponse }
    )
    if (!parsed.success) return parsed.response

    const { organizationId } = parsed.data.query

    try {
      const baseQuery = db
        .select({
          id: permissionGroup.id,
          organizationId: permissionGroup.organizationId,
          organizationName: organization.name,
          name: permissionGroup.name,
          description: permissionGroup.description,
          isDefault: permissionGroup.isDefault,
          createdAt: permissionGroup.createdAt,
          createdByUserId: permissionGroup.createdBy,
          createdByEmail: user.email,
        })
        .from(permissionGroup)
        .leftJoin(organization, eq(permissionGroup.organizationId, organization.id))
        .leftJoin(user, eq(permissionGroup.createdBy, user.id))

      const groups = organizationId
        ? await baseQuery.where(eq(permissionGroup.organizationId, organizationId))
        : await baseQuery

      const groupsWithCounts = await Promise.all(
        groups.map(async (group) => {
          const [memberCount] = await db
            .select({ count: count() })
            .from(permissionGroupMember)
            .where(eq(permissionGroupMember.permissionGroupId, group.id))

          return {
            id: group.id,
            organizationId: group.organizationId,
            organizationName: group.organizationName,
            name: group.name,
            description: group.description,
            isDefault: group.isDefault,
            memberCount: memberCount?.count ?? 0,
            createdAt: group.createdAt.toISOString(),
            createdByUserId: group.createdByUserId,
            createdByEmail: group.createdByEmail,
          } as AdminV1PermissionGroup
        })
      )

      logger.info('Admin API: Listed permission groups', {
        organizationId,
        count: groupsWithCounts.length,
      })

      return singleResponse({
        data: groupsWithCounts,
        pagination: {
          total: groupsWithCounts.length,
          limit: groupsWithCounts.length,
          offset: 0,
          hasMore: false,
        },
      })
    } catch (error) {
      logger.error('Admin API: Failed to list permission groups', {
        error,
        organizationId,
      })
      return internalErrorResponse('Failed to list permission groups')
    }
  })
)

export const DELETE = withRouteHandler(
  withAdminAuth(async (request) => {
    const parsed = await parseRequest(
      adminV1DeleteAccessControlContract,
      request,
      {},
      {
        validationErrorResponse: adminValidationErrorResponse,
      }
    )
    if (!parsed.success) return parsed.response

    const { organizationId, reason: rawReason } = parsed.data.query
    // The contract's refine guarantees this at the boundary; this explicit guard
    // narrows the type (avoiding a non-null assertion) and stays correct even if
    // the contract changes.
    if (!organizationId) {
      return badRequestResponse('organizationId is required')
    }
    const reason = rawReason || 'Enterprise plan churn cleanup'

    try {
      const existingGroups = await db
        .select({
          id: permissionGroup.id,
          name: permissionGroup.name,
        })
        .from(permissionGroup)
        .where(eq(permissionGroup.organizationId, organizationId))

      if (existingGroups.length === 0) {
        logger.info('Admin API: No permission groups to delete', { organizationId })
        return singleResponse({
          success: true,
          deletedCount: 0,
          membersRemoved: 0,
          message: 'No permission groups found for the given scope',
        })
      }

      const groupIds = existingGroups.map((g) => g.id)

      const [memberCountResult] = await db
        .select({ count: sql<number>`count(*)` })
        .from(permissionGroupMember)
        .where(inArray(permissionGroupMember.permissionGroupId, groupIds))

      const membersToRemove = Number(memberCountResult?.count ?? 0)

      await db.delete(permissionGroup).where(inArray(permissionGroup.id, groupIds))

      for (const group of existingGroups) {
        recordAudit({
          actorId: 'admin-api',
          action: AuditAction.PERMISSION_GROUP_DELETED,
          resourceType: AuditResourceType.PERMISSION_GROUP,
          resourceId: group.id,
          resourceName: group.name,
          description: `Admin API deleted permission group "${group.name}"`,
          metadata: { reason, organizationId },
          request,
        })
      }

      logger.info('Admin API: Deleted permission groups', {
        organizationId,
        deletedCount: existingGroups.length,
        membersRemoved: membersToRemove,
        reason,
      })

      return singleResponse({
        success: true,
        deletedCount: existingGroups.length,
        membersRemoved: membersToRemove,
        reason,
      })
    } catch (error) {
      logger.error('Admin API: Failed to delete permission groups', {
        error,
        organizationId,
      })
      return internalErrorResponse('Failed to delete permission groups')
    }
  })
)
