import express from 'express';
// import { prisma } from '@cloneweb/database';
// import { validateProjectCreation, validatePagination } from '@cloneweb/shared';
import { authenticateToken, requireSubscription } from '../middleware/auth';
import { requirePermission, requireProjectAccess, AuthorizedRequest, addUserPermissions } from '../middleware/authorization';
import { RBACService } from '../services/rbac.service';

// Temporary mock implementations
const prisma = {
  project: {
    findMany: async (params: any): Promise<any[]> => [],
    count: async (params: any): Promise<number> => 0,
    create: async (params: any): Promise<any> => ({
      id: 'mock-project-id',
      name: params.data.name,
      description: params.data.description,
      sourceUrl: params.data.sourceUrl,
      status: 'CREATED',
      createdAt: new Date(),
      settings: params.data.settings || {}
    }),
    findFirst: async (params: any): Promise<any> => ({
      id: 'mock-project-id',
      name: 'Mock Project',
      status: 'CREATED',
      user: { id: 'mock-user-id', email: 'mock@example.com' }
    }),
    update: async (params: any): Promise<any> => ({
      id: params.where.id,
      name: 'Updated Project',
      updatedAt: new Date()
    }),
    delete: async (params: any): Promise<any> => ({ id: params.where.id })
  }
};

const validateProjectCreation = (data: any) => {
  if (!data.name || !data.sourceUrl) {
    throw new Error('Name and source URL are required');
  }
  return data;
};

const validatePagination = (data: any) => ({
  page: parseInt(data.page) || 1,
  limit: parseInt(data.limit) || 20
});

const router = express.Router();

// Apply authentication and user permissions to all routes
router.use(authenticateToken);
router.use(addUserPermissions('id'));

// Get user's projects
router.get('/', async (req: AuthorizedRequest, res, next) => {
  try {
    const pagination = validatePagination(req.query);
    const skip = (pagination.page - 1) * pagination.limit;
    
    const [projects, total] = await Promise.all([
      prisma.project.findMany({
        where: { userId: req.user!.id },
        select: {
          id: true,
          name: true,
          description: true,
          sourceUrl: true,
          status: true,
          createdAt: true,
          updatedAt: true,
          _count: {
            select: {
              pages: true,
              assets: true,
              components: true
            }
          }
        },
        orderBy: { updatedAt: 'desc' },
        skip,
        take: pagination.limit
      }),
      prisma.project.count({
        where: { userId: req.user!.id }
      })
    ]);
    
    const totalPages = Math.ceil(total / pagination.limit);
    
    res.json({
      success: true,
      data: projects,
      pagination: {
        page: pagination.page,
        limit: pagination.limit,
        total,
        totalPages
      }
    });
  } catch (error) {
    next(error);
  }
});

// Create new project
router.post('/', requirePermission('project:create'), async (req: AuthorizedRequest, res, next) => {
  try {
    const validatedData = validateProjectCreation(req.body);
    
    // Check subscription limits
    const userProjects = await prisma.project.count({
      where: { userId: req.user!.id }
    });
    
    const limits = {
      FREE: 3,
      BASIC: 10,
      PRO: 50,
      ENTERPRISE: -1 // unlimited
    };
    
    const userLimit = limits[req.user!.subscription as keyof typeof limits];
    
    if (userLimit !== -1 && userProjects >= userLimit) {
      return res.status(403).json({
        success: false,
        error: `Project limit reached for ${req.user!.subscription} subscription`,
        code: 'PROJECT_LIMIT_EXCEEDED'
      });
    }
    
    const project = await prisma.project.create({
      data: {
        name: validatedData.name,
        description: validatedData.description,
        sourceUrl: validatedData.sourceUrl,
        userId: req.user!.id,
        settings: validatedData.settings || {},
        analytics: {
          create: {
            totalPages: 0,
            totalAssets: 0,
            totalComponents: 0
          }
        }
      },
      select: {
        id: true,
        name: true,
        description: true,
        sourceUrl: true,
        status: true,
        createdAt: true,
        settings: true
      }
    });
    
    // Assign project owner role to the creator
    RBACService.assignRole(req.user!.id, 'project-owner', project.id, req.user!.id);
    
    res.status(201).json({
      success: true,
      data: project,
      message: 'Project created successfully',
      userPermissions: (req as any).userPermissions
    });
  } catch (error) {
    next(error);
  }
});

// Get project by ID
router.get('/:id', requireProjectAccess('read', 'id'), async (req: AuthorizedRequest, res, next) => {
  try {
    const project = await prisma.project.findFirst({
      where: {
        id: req.params.id,
        OR: [
          { userId: req.user!.id },
          {
            collaborations: {
              some: { userId: req.user!.id }
            }
          }
        ]
      },
      select: {
        id: true,
        name: true,
        description: true,
        sourceUrl: true,
        status: true,
        settings: true,
        createdAt: true,
        updatedAt: true,
        user: {
          select: {
            id: true,
            email: true,
            firstName: true,
            lastName: true
          }
        },
        analytics: {
          select: {
            cloneAccuracy: true,
            processingTime: true,
            totalPages: true,
            totalAssets: true,
            totalComponents: true,
            lastUpdated: true
          }
        },
        _count: {
          select: {
            pages: true,
            assets: true,
            components: true,
            collaborations: true
          }
        }
      }
    });
    
    if (!project) {
      return res.status(404).json({
        success: false,
        error: 'Project not found',
        code: 'PROJECT_NOT_FOUND'
      });
    }
    
    res.json({
      success: true,
      data: project
    });
  } catch (error) {
    next(error);
  }
});

// Update project
router.patch('/:id', requireProjectAccess('update', 'id'), async (req: AuthorizedRequest, res, next) => {
  try {
    const { name, description, settings } = req.body;
    
    // Check if user owns the project
    const existingProject = await prisma.project.findFirst({
      where: {
        id: req.params.id,
        userId: req.user!.id
      }
    });
    
    if (!existingProject) {
      return res.status(404).json({
        success: false,
        error: 'Project not found or access denied',
        code: 'PROJECT_NOT_FOUND'
      });
    }
    
    const updatedProject = await prisma.project.update({
      where: { id: req.params.id },
      data: {
        ...(name && { name }),
        ...(description !== undefined && { description }),
        ...(settings && { settings })
      },
      select: {
        id: true,
        name: true,
        description: true,
        sourceUrl: true,
        status: true,
        settings: true,
        updatedAt: true
      }
    });
    
    res.json({
      success: true,
      data: updatedProject,
      message: 'Project updated successfully'
    });
  } catch (error) {
    next(error);
  }
});

// Delete project
router.delete('/:id', requireProjectAccess('delete', 'id'), async (req: AuthorizedRequest, res, next) => {
  try {
    // Check if user owns the project
    const existingProject = await prisma.project.findFirst({
      where: {
        id: req.params.id,
        userId: req.user!.id
      }
    });
    
    if (!existingProject) {
      return res.status(404).json({
        success: false,
        error: 'Project not found or access denied',
        code: 'PROJECT_NOT_FOUND'
      });
    }
    
    // Delete project (cascade will handle related records)
    await prisma.project.delete({
      where: { id: req.params.id }
    });
    
    // Remove all project-specific role assignments
    const projectMembers = RBACService.getProjectMembers(req.params.id);
    projectMembers.forEach(member => {
      member.roles.forEach(role => {
        RBACService.removeRole(member.userId, role.roleId, req.params.id);
      });
    });
    
    res.json({
      success: true,
      message: 'Project deleted successfully'
    });
  } catch (error) {
    next(error);
  }
});

// Start project cloning
router.post('/:id/clone', requirePermission('crawl:start', 'id'), requireSubscription('BASIC'), async (req: AuthorizedRequest, res, next) => {
  try {
    const project = await prisma.project.findFirst({
      where: {
        id: req.params.id,
        userId: req.user!.id
      }
    });
    
    if (!project) {
      return res.status(404).json({
        success: false,
        error: 'Project not found',
        code: 'PROJECT_NOT_FOUND'
      });
    }
    
    if (project.status === 'CRAWLING' || project.status === 'PROCESSING') {
      return res.status(400).json({
        success: false,
        error: 'Project is already being processed',
        code: 'PROJECT_ALREADY_PROCESSING'
      });
    }
    
    // Update project status
    await prisma.project.update({
      where: { id: req.params.id },
      data: { status: 'CRAWLING' }
    });
    
    // TODO: Queue crawling job
    // This would typically send a message to the crawler service
    
    res.json({
      success: true,
      message: 'Cloning process started',
      data: {
        projectId: project.id,
        status: 'CRAWLING'
      }
    });
  } catch (error) {
    next(error);
  }
});

export default router;