import { NextAuthOptions } from "next-auth"
import GoogleProvider from "next-auth/providers/google"
import GitHubProvider from "next-auth/providers/github"
import CredentialsProvider from "next-auth/providers/credentials"
import { env } from "./env"
import { UserRole } from "@/types/database"
import {
  getNextcloudUserProfile,
  getNextcloudUserGroups,
  determineUserRole
} from "./nextcloud-client"

export const authOptions: NextAuthOptions = {
  // Note: Database adapter will be configured via Supabase MCP
  // For now, using JWT strategy without database adapter
  providers: [
    // Credentials provider for email/password login (admin fallback) and Nextcloud OAuth completion
    CredentialsProvider({
      name: "credentials",
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" },
        nextcloud_token: { label: "Nextcloud Token", type: "text" },
      },
      async authorize(credentials, req) {
        console.log("Authorize called with:", credentials)

        // Handle Nextcloud OAuth completion
        if (credentials?.nextcloud_token) {
          console.log("Nextcloud OAuth completion with token")

          // Get cookies from request
          const cookies = req.headers?.cookie
          if (!cookies) {
            console.error("No cookies found")
            return null
          }

          // Parse cookies manually
          const cookieMap = new Map(
            cookies.split(';').map(c => {
              const [key, ...values] = c.trim().split('=')
              return [key, values.join('=')]
            })
          )

          const storedToken = cookieMap.get('nextcloud_one_time_token')
          const userId = cookieMap.get('nextcloud_user_id')

          console.log("Stored token:", storedToken ? "present" : "missing")
          console.log("User ID:", userId ? userId : "missing")

          if (!storedToken || !userId || storedToken !== credentials.nextcloud_token) {
            console.error("Token validation failed")
            return null
          }

          // Fetch user from database
          const { getUserById } = await import('@/lib/db')
          const user = await getUserById(userId)

          if (!user) {
            console.error("User not found")
            return null
          }

          console.log("Nextcloud user authenticated:", user.email)
          return {
            id: user.id,
            email: user.email,
            name: user.name,
            role: user.role,
          }
        }

        // Handle regular credentials login
        if (!credentials?.email || !credentials?.password) {
          console.log("Missing email or password")
          return null
        }

        console.log("Email received:", credentials.email)
        console.log("Password received:", credentials.password ? "***" : "empty")

        // Seed admin user for nicholai@biohazardvfx.com
        if (credentials.email === "nicholai@biohazardvfx.com") {
          console.log("Admin user recognized!")
          return {
            id: "admin-nicholai",
            email: "nicholai@biohazardvfx.com",
            name: "Nicholai",
            role: UserRole.SUPER_ADMIN,
          }
        }

        // For development: Accept any other email/password combination
        console.log("Using fallback user creation")
        const user = {
          id: "dev-user-" + Date.now(),
          email: credentials.email,
          name: credentials.email.split("@")[0],
          role: UserRole.SUPER_ADMIN, // Give admin access for testing
        }

        console.log("Created user:", user)
        return user
      }
    }),
    
    // Google OAuth provider (optional)
    ...(env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET ? [
      GoogleProvider({
        clientId: env.GOOGLE_CLIENT_ID,
        clientSecret: env.GOOGLE_CLIENT_SECRET,
      })
    ] : []),
    
    // GitHub OAuth provider (optional)
    ...(env.GITHUB_CLIENT_ID && env.GITHUB_CLIENT_SECRET ? [
      GitHubProvider({
        clientId: env.GITHUB_CLIENT_ID,
        clientSecret: env.GITHUB_CLIENT_SECRET,
      })
    ] : []),
  ],
  session: {
    strategy: "jwt",
    maxAge: 30 * 24 * 60 * 60, // 30 days
  },
  callbacks: {
    async jwt({ token, user, account }) {
      // Add user role to JWT token
      if (user) {
        // Use the role from the user object (set in authorize function)
        token.role = (user as any).role || UserRole.CLIENT
        token.userId = user.id
      }
      return token
    },
    async session({ session, token }) {
      // Add user role and ID to session
      if (token) {
        session.user.id = token.userId as string
        session.user.role = token.role as UserRole
      }
      return session
    },
    async signIn({ user, account, profile }) {
      // Custom sign-in logic
      // Note: Nextcloud OAuth auto-provisioning happens in custom callback handler
      return true
    },
    async redirect({ url, baseUrl }) {
      // Follows NextAuth.js best practices for redirect
      if (url.startsWith("/")) return `${baseUrl}${url}`
      else if (new URL(url).origin === baseUrl) return url
      return `${baseUrl}/admin`
    },
  },
  pages: {
    signIn: "/auth/signin",
    error: "/auth/error",
  },
  events: {
    async signIn({ user, account, profile, isNewUser }) {
      // Log sign-in events
      console.log(`User ${user.email} signed in`)
    },
    async signOut({ session, token }) {
      // Log sign-out events
      console.log(`User signed out`)
    },
  },
  debug: env.NODE_ENV === "development",
}

/**
 * Utility function to get server-side session
 */
export async function getServerSession() {
  const { getServerSession: getNextAuthServerSession } = await import("next-auth/next")
  return getNextAuthServerSession(authOptions)
}

/**
 * Route protection utility
 * @param requiredRole - Minimum role required to access the route
 */
export async function requireAuth(requiredRole?: UserRole) {
  const session = await getServerSession()
  
  if (!session) {
    throw new Error("Authentication required")
  }
  
  if (requiredRole && !hasRole(session.user.role, requiredRole)) {
    throw new Error("Insufficient permissions")
  }
  
  return session
}

/**
 * Check if user has required role or higher
 */
export function hasRole(userRole: UserRole, requiredRole: UserRole): boolean {
  const roleHierarchy = {
    [UserRole.CLIENT]: 0,
    [UserRole.ARTIST]: 1,
    [UserRole.SHOP_ADMIN]: 2,
    [UserRole.SUPER_ADMIN]: 3,
  }
  
  return roleHierarchy[userRole] >= roleHierarchy[requiredRole]
}

/**
 * Check if user is admin (SHOP_ADMIN or SUPER_ADMIN)
 */
export function isAdmin(role: UserRole): boolean {
  return role === UserRole.SHOP_ADMIN || role === UserRole.SUPER_ADMIN
}

/**
 * Check if user is super admin
 */
export function isSuperAdmin(role: UserRole): boolean {
  return role === UserRole.SUPER_ADMIN
}

/**
 * Get current artist session
 * Returns the artist record and user data if the logged-in user is an artist
 */
export async function getArtistSession() {
  const session = await getServerSession()
  
  if (!session?.user) {
    return null
  }
  
  // Check if user has ARTIST role
  const userRole = session.user.role
  if (userRole !== UserRole.ARTIST && !isAdmin(userRole)) {
    return null
  }
  
  // Import db function dynamically to avoid circular dependencies
  const { getArtistByUserId } = await import('@/lib/db')
  const artist = await getArtistByUserId(session.user.id)
  
  if (!artist) {
    return null
  }
  
  return {
    artist,
    user: session.user
  }
}

/**
 * Require artist authentication
 * Throws error if user is not an artist, otherwise returns artist and user data
 */
export async function requireArtistAuth() {
  const artistSession = await getArtistSession()
  
  if (!artistSession) {
    throw new Error("Artist authentication required")
  }
  
  return artistSession
}

/**
 * Check if a user can edit a specific artist profile
 * Returns true if the user is the artist themselves, or has admin privileges
 */
export async function canEditArtist(userId: string, artistId: string): Promise<boolean> {
  const session = await getServerSession()
  
  if (!session?.user) {
    return false
  }
  
  // Admins can edit any artist
  if (isAdmin(session.user.role)) {
    return true
  }
  
  // Check if this user owns the artist profile
  const { getArtistByUserId } = await import('@/lib/db')
  const artist = await getArtistByUserId(userId)
  
  return artist?.id === artistId
}

// Extend NextAuth types
declare module "next-auth" {
  interface Session {
    user: {
      id: string
      email: string
      name: string
      image?: string
      role: UserRole
    }
  }
  
  interface User {
    role: UserRole
  }
}

declare module "next-auth/jwt" {
  interface JWT {
    userId: string
    role: UserRole
  }
}
