"use client";

import React from "react";
import { useAuth, usePermissions, usePermissionGuard } from "./hooks";
import { UserRole } from "./middleware";
import { Permission } from "./rbac";

// 타입 정의
interface ProtectedRouteProps {
  children: React.ReactNode;
  requiredRoles?: UserRole[];
  requiredPermissions?: Permission[];
  fallback?: React.ReactNode;
  redirectTo?: string;
}

interface PermissionGuardProps {
  children: React.ReactNode;
  permissions: Permission[];
  fallback?: React.ReactNode;
  requireAll?: boolean;
}

interface RoleGuardProps {
  children: React.ReactNode;
  roles: UserRole[];
  fallback?: React.ReactNode;
  requireExact?: boolean;
}

interface ConditionalRenderProps {
  children: React.ReactNode;
  condition: boolean;
  fallback?: React.ReactNode;
}

/**
 * 인증이 필요한 라우트를 보호하는 컴포넌트
 */
export function ProtectedRoute({
  children,
  requiredRoles,
  requiredPermissions,
  fallback,
  redirectTo,
}: ProtectedRouteProps) {
  const { user, isLoading } = useAuth();
  const { hasAnyPermission } = usePermissions();

  // 로딩 중
  if (isLoading) {
    return (
      <div className="flex items-center justify-center min-h-screen">
        <div className="animate-spin rounded-full h-32 w-32 border-b-2 border-blue-600"></div>
      </div>
    );
  }

  // 인증되지 않은 사용자
  if (!user) {
    if (redirectTo) {
      window.location.href = `${redirectTo}?callbackUrl=${encodeURIComponent(
        window.location.pathname
      )}`;
      return null;
    }

    return (
      fallback || (
        <div className="flex items-center justify-center min-h-screen">
          <div className="text-center">
            <h2 className="text-2xl font-bold text-gray-900 mb-4">
              로그인이 필요합니다
            </h2>
            <p className="text-gray-600 mb-6">
              이 페이지에 접근하려면 로그인해야 합니다.
            </p>
            <a
              href="/auth/signin"
              className="bg-blue-600 text-white px-6 py-2 rounded-md hover:bg-blue-700"
            >
              로그인
            </a>
          </div>
        </div>
      )
    );
  }

  // 역할 확인
  if (requiredRoles && !requiredRoles.includes(user.role)) {
    return (
      fallback || (
        <div className="flex items-center justify-center min-h-screen">
          <div className="text-center">
            <h2 className="text-2xl font-bold text-red-600 mb-4">
              접근 권한이 없습니다
            </h2>
            <p className="text-gray-600">이 페이지에 접근할 권한이 없습니다.</p>
          </div>
        </div>
      )
    );
  }

  // 권한 확인
  if (requiredPermissions && !hasAnyPermission(requiredPermissions)) {
    return (
      fallback || (
        <div className="flex items-center justify-center min-h-screen">
          <div className="text-center">
            <h2 className="text-2xl font-bold text-red-600 mb-4">
              권한이 부족합니다
            </h2>
            <p className="text-gray-600">이 기능을 사용할 권한이 없습니다.</p>
          </div>
        </div>
      )
    );
  }

  return <>{children}</>;
}

/**
 * 특정 권한이 있는 경우에만 렌더링하는 컴포넌트
 */
export function PermissionGuard({
  children,
  permissions,
  fallback,
  requireAll = false,
}: PermissionGuardProps) {
  const { hasPermission, hasAllPermissions, hasAnyPermission } =
    usePermissions();

  const hasRequiredPermissions = requireAll
    ? hasAllPermissions(permissions)
    : hasAnyPermission(permissions);

  if (!hasRequiredPermissions) {
    return <>{fallback}</>;
  }

  return <>{children}</>;
}

/**
 * 특정 역할이 있는 경우에만 렌더링하는 컴포넌트
 */
export function RoleGuard({
  children,
  roles,
  fallback,
  requireExact = false,
}: RoleGuardProps) {
  const { user } = useAuth();

  if (!user) {
    return <>{fallback}</>;
  }

  const hasRequiredRole = requireExact
    ? roles.includes(user.role)
    : roles.some((role) => {
        // 역할 계층 구조 고려
        if (role === UserRole.GUEST) return true;
        if (role === UserRole.VIEWER)
          return [UserRole.VIEWER, UserRole.EDITOR, UserRole.ADMIN].includes(
            user.role
          );
        if (role === UserRole.EDITOR)
          return [UserRole.EDITOR, UserRole.ADMIN].includes(user.role);
        if (role === UserRole.ADMIN) return user.role === UserRole.ADMIN;
        return false;
      });

  if (!hasRequiredRole) {
    return <>{fallback}</>;
  }

  return <>{children}</>;
}

/**
 * 조건부 렌더링 컴포넌트
 */
export function ConditionalRender({
  children,
  condition,
  fallback,
}: ConditionalRenderProps) {
  return condition ? <>{children}</> : <>{fallback}</>;
}

/**
 * 관리자 전용 컴포넌트
 */
export function AdminOnly({
  children,
  fallback,
}: {
  children: React.ReactNode;
  fallback?: React.ReactNode;
}) {
  return (
    <RoleGuard roles={[UserRole.ADMIN]} fallback={fallback} requireExact>
      {children}
    </RoleGuard>
  );
}

/**
 * 편집자 이상 컴포넌트
 */
export function EditorOrAbove({
  children,
  fallback,
}: {
  children: React.ReactNode;
  fallback?: React.ReactNode;
}) {
  return (
    <RoleGuard roles={[UserRole.EDITOR, UserRole.ADMIN]} fallback={fallback}>
      {children}
    </RoleGuard>
  );
}

/**
 * 인증된 사용자 전용 컴포넌트
 */
export function AuthenticatedOnly({
  children,
  fallback,
}: {
  children: React.ReactNode;
  fallback?: React.ReactNode;
}) {
  return (
    <RoleGuard
      roles={[UserRole.VIEWER, UserRole.EDITOR, UserRole.ADMIN]}
      fallback={fallback}
    >
      {children}
    </RoleGuard>
  );
}

/**
 * 권한 기반 버튼 컴포넌트
 */
interface PermissionButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  permissions: Permission[];
  requireAll?: boolean;
  children: React.ReactNode;
}

export function PermissionButton({
  permissions,
  requireAll = false,
  children,
  ...props
}: PermissionButtonProps) {
  const canRender = usePermissionGuard(permissions);

  if (!canRender) {
    return null;
  }

  return <button {...props}>{children}</button>;
}

/**
 * 권한 기반 링크 컴포넌트
 */
interface PermissionLinkProps
  extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
  permissions: Permission[];
  requireAll?: boolean;
  children: React.ReactNode;
}

export function PermissionLink({
  permissions,
  requireAll = false,
  children,
  ...props
}: PermissionLinkProps) {
  const canRender = usePermissionGuard(permissions);

  if (!canRender) {
    return null;
  }

  return <a {...props}>{children}</a>;
}

/**
 * 사용자 정보 표시 컴포넌트
 */
export function UserInfo({ className }: { className?: string }) {
  const { user } = useAuth();

  if (!user) {
    return null;
  }

  const getRoleDisplayName = (role: UserRole) => {
    switch (role) {
      case UserRole.ADMIN:
        return "관리자";
      case UserRole.EDITOR:
        return "편집자";
      case UserRole.VIEWER:
        return "뷰어";
      case UserRole.GUEST:
        return "게스트";
      default:
        return role;
    }
  };

  const getRoleBadgeColor = (role: UserRole) => {
    switch (role) {
      case UserRole.ADMIN:
        return "bg-red-100 text-red-800";
      case UserRole.EDITOR:
        return "bg-blue-100 text-blue-800";
      case UserRole.VIEWER:
        return "bg-green-100 text-green-800";
      case UserRole.GUEST:
        return "bg-gray-100 text-gray-800";
      default:
        return "bg-gray-100 text-gray-800";
    }
  };

  return (
    <div className={`flex items-center space-x-3 ${className}`}>
      {user.image && (
        <img
          src={user.image}
          alt={user.name || user.email}
          className="w-8 h-8 rounded-full"
        />
      )}
      <div>
        <div className="text-sm font-medium text-gray-900">
          {user.name || user.email}
        </div>
        <div className="flex items-center space-x-2">
          <span className="text-xs text-gray-500">{user.email}</span>
          <span
            className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${getRoleBadgeColor(
              user.role
            )}`}
          >
            {getRoleDisplayName(user.role)}
          </span>
        </div>
      </div>
    </div>
  );
}

/**
 * 권한 기반 메뉴 아이템 컴포넌트
 */
interface PermissionMenuItemProps {
  permissions: Permission[];
  children: React.ReactNode;
  className?: string;
  onClick?: () => void;
}

export function PermissionMenuItem({
  permissions,
  children,
  className,
  onClick,
}: PermissionMenuItemProps) {
  const canRender = usePermissionGuard(permissions);

  if (!canRender) {
    return null;
  }

  return (
    <div className={className} onClick={onClick}>
      {children}
    </div>
  );
}
