const path = require('path');
const { models } = require(path.resolve(process.env.ROOT_PATH, './db/db.js'));
const BaseController = require(path.resolve(process.env.ROOT_PATH, './controllers/BaseController.js'));
const { subDays } = require('date-fns');

class StatsController extends BaseController {
  constructor() {
    super();
    
  }

  /**
   * Get overall system statistics
   * 
   * @swagger
   * /stats/system:
   *   get:
   *     summary: Get system statistics
   *     description: Retrieves overall system statistics including mailbox and domain counts
   *     tags: [Statistics]
   *     security:
   *       - bearerAuth: []
   *     responses:
   *       200:
   *         description: System statistics
   *         content:
   *           application/json:
   *             schema:
   *               type: object
   *               properties:
   *                 mailboxes:
   *                   type: object
   *                   properties:
   *                     total:
   *                       type: integer
   *                       description: Total number of mailboxes
   *                     active:
   *                       type: integer
   *                       description: Number of active mailboxes
   *                     expiringToday:
   *                       type: integer
   *                       description: Number of mailboxes expiring today
   *                 domains:
   *                   type: object
   *                   properties:
   *                     total:
   *                       type: integer
   *                       description: Total number of domains
   *                     active:
   *                       type: integer
   *                       description: Number of active domains
   *                 creationStats:
   *                   type: array
   *                   description: Mailbox creation statistics for the last 7 days
   *                   items:
   *                     type: object
   *                     properties:
   *                       date:
   *                         type: string
   *                         format: date
   *                       mailboxesCreated:
   *                         type: integer
   *       500:
   *         description: Server error
   */
  async getSystemStats(req, res) {
    try {
      // Get total counts
      const totalMailboxes = await models.Mailbox.query().count('* as count').first();
      const activeMailboxes = await models.Mailbox.query()
        .where('active', 1)
        .count('* as count')
        .first();
      const expiringToday = await models.Mailbox.query()
        .where('expires', '<', new Date(new Date().setHours(23, 59, 59, 999)).toISOString().slice(0, 19).replace('T', ' '))
        .where('expires', '>', new Date().toISOString().slice(0, 19).replace('T', ' '))
        .count('* as count')
        .first();
      const totalDomains = await models.Domain.query().count('* as count').first();
      const activeDomains = await models.Domain.query()
        .where('active', 1)
        .count('* as count')
        .first();
      
      // Get creation stats for the last 7 days
      const last7Days = [];
      for (let i = 6; i >= 0; i--) {
        const date = subDays(new Date(), i);
        const formattedDate = date.toISOString().slice(0, 10);
        
        // Get mailboxes created on this date
        const mailboxesCreated = await models.Mailbox.query()
          .where('created', 'like', `${formattedDate}%`)
          .count('* as count')
          .first();
        
        last7Days.push({
          date: formattedDate,
          mailboxesCreated: parseInt(mailboxesCreated.count) || 0
        });
      }
      
      return res.json({
        mailboxes: {
          total: parseInt(totalMailboxes.count) || 0,
          active: parseInt(activeMailboxes.count) || 0,
          expiringToday: parseInt(expiringToday.count) || 0
        },
        domains: {
          total: parseInt(totalDomains.count) || 0,
          active: parseInt(activeDomains.count) || 0
        },
        creationStats: last7Days
      });
    } catch (error) {
      console.error('Error fetching system stats:', error);
      return res.status(500).json({ error: 'Failed to fetch system statistics' });
    }
  }

  /**
   * Get mailbox statistics
   * 
   * @swagger
   * /stats/mailboxes:
   *   get:
   *     summary: Get mailbox statistics
   *     description: Retrieves detailed statistics about mailboxes
   *     tags: [Statistics]
   *     security:
   *       - bearerAuth: []
   *     responses:
   *       200:
   *         description: Mailbox statistics
   *         content:
   *           application/json:
   *             schema:
   *               type: object
   *               properties:
   *                 expiryStats:
   *                   type: object
   *                   properties:
   *                     expired:
   *                       type: integer
   *                       description: Number of expired mailboxes
   *                     expiringSoon:
   *                       type: integer
   *                       description: Number of mailboxes expiring within 3 days
   *                 creationByDay:
   *                   type: array
   *                   description: Mailbox creation statistics for the last 30 days
   *                   items:
   *                     type: object
   *                     properties:
   *                       date:
   *                         type: string
   *                         format: date
   *                       count:
   *                         type: integer
   *                 topDomains:
   *                   type: array
   *                   description: Top 10 domains by mailbox count
   *                   items:
   *                     type: object
   *                     properties:
   *                       domain:
   *                         type: string
   *                       count:
   *                         type: integer
   *       500:
   *         description: Server error
   */
  async getMailboxStats(req, res) {
    try {
      // Get mailboxes by expiry status
      const expired = await models.Mailbox.query()
        .where('expires', '<', new Date().toISOString().slice(0, 19).replace('T', ' '))
        .count('* as count')
        .first();
      
      const expiringSoon = await models.Mailbox.query()
        .where('expires', '>', new Date().toISOString().slice(0, 19).replace('T', ' '))
        .where('expires', '<', new Date(new Date().getTime() + 3 * 24 * 60 * 60 * 1000).toISOString().slice(0, 19).replace('T', ' '))
        .count('* as count')
        .first();
      
      // Get mailboxes by creation date (last 30 days)
      const creationByDay = [];
      for (let i = 29; i >= 0; i--) {
        const date = subDays(new Date(), i);
        const formattedDate = date.toISOString().slice(0, 10);
        
        const created = await models.Mailbox.query()
          .where('created', 'like', `${formattedDate}%`)
          .count('* as count')
          .first();
        
        creationByDay.push({
          date: formattedDate,
          count: parseInt(created.count) || 0
        });
      }
      
      // Get top domains by mailbox count
      const topDomains = await models.Mailbox.query()
        .select('domain')
        .count('* as count')
        .groupBy('domain')
        .orderBy('count', 'desc')
        .limit(10);
      
      return res.json({
        expiryStats: {
          expired: parseInt(expired.count) || 0,
          expiringSoon: parseInt(expiringSoon.count) || 0
        },
        creationByDay,
        topDomains: topDomains.map(d => ({
          domain: d.domain,
          count: parseInt(d.count) || 0
        }))
      });
    } catch (error) {
      console.error('Error fetching mailbox stats:', error);
      return res.status(500).json({ error: 'Failed to fetch mailbox statistics' });
    }
  }

  /**
   * Get domain statistics
   * 
   * @swagger
   * /stats/domains:
   *   get:
   *     summary: Get domain statistics
   *     description: Retrieves detailed statistics about domains
   *     tags: [Statistics]
   *     security:
   *       - bearerAuth: []
   *     responses:
   *       200:
   *         description: Domain statistics
   *         content:
   *           application/json:
   *             schema:
   *               type: object
   *               properties:
   *                 domains:
   *                   type: object
   *                   properties:
   *                     total:
   *                       type: integer
   *                       description: Total number of domains
   *                     active:
   *                       type: integer
   *                       description: Number of active domains
   *                     inactive:
   *                       type: integer
   *                       description: Number of inactive domains
   *                 topDomains:
   *                   type: array
   *                   description: Top 10 domains by mailbox count
   *                   items:
   *                     type: object
   *                     properties:
   *                       domain:
   *                         type: string
   *                       mailboxCount:
   *                         type: integer
   *                 domainDetails:
   *                   type: array
   *                   description: Detailed information about all domains
   *                   items:
   *                     type: object
   *                     properties:
   *                       domain:
   *                         type: string
   *                       description:
   *                         type: string
   *                       active:
   *                         type: boolean
   *                       mailboxCount:
   *                         type: integer
   *       500:
   *         description: Server error
   */
  async getDomainStats(req, res) {
    try {
      // Get all domains with mailbox counts
      const domains = await models.Domain.query()
        .select('domain.domain', 'domain.description', 'domain.active')
        .leftJoin('mailbox', 'domain.domain', 'mailbox.domain')
        .groupBy('domain.domain')
        .count('mailbox.username as mailboxCount');
      
      // Get active vs inactive domains
      const activeDomains = domains.filter(d => d.active === 1).length;
      const inactiveDomains = domains.filter(d => d.active === 0).length;
      
      // Get domains with most mailboxes
      const topDomains = [...domains]
        .sort((a, b) => parseInt(b.mailboxCount) - parseInt(a.mailboxCount))
        .slice(0, 10)
        .map(d => ({
          domain: d.domain,
          mailboxCount: parseInt(d.mailboxCount) || 0
        }));
      
      return res.json({
        domains: {
          total: domains.length,
          active: activeDomains,
          inactive: inactiveDomains
        },
        topDomains,
        domainDetails: domains.map(d => ({
          domain: d.domain,
          description: d.description,
          active: d.active === 1,
          mailboxCount: parseInt(d.mailboxCount) || 0
        }))
      });
    } catch (error) {
      console.error('Error fetching domain stats:', error);
      return res.status(500).json({ error: 'Failed to fetch domain statistics' });
    }
  }

  /**
   * Get user statistics
   * 
   * @swagger
   * /stats/users:
   *   get:
   *     summary: Get user statistics
   *     description: Retrieves detailed statistics about users
   *     tags: [Statistics]
   *     security:
   *       - bearerAuth: []
   *     responses:
   *       200:
   *         description: User statistics
   *         content:
   *           application/json:
   *             schema:
   *               type: object
   *               properties:
   *                 users:
   *                   type: object
   *                   properties:
   *                     total:
   *                       type: integer
   *                       description: Total number of users
   *                     admin:
   *                       type: integer
   *                       description: Number of admin users
   *                     active:
   *                       type: integer
   *                       description: Number of active users
   *                 creationByDay:
   *                   type: array
   *                   description: User creation statistics for the last 30 days
   *                   items:
   *                     type: object
   *                     properties:
   *                       date:
   *                         type: string
   *                         format: date
   *                       count:
   *                         type: integer
   *                 invites:
   *                   type: object
   *                   properties:
   *                     active:
   *                       type: integer
   *                       description: Number of active invites
   *       500:
   *         description: Server error
   */
  async getUserStats(req, res) {
    try {
      // Get total users count
      const totalUsers = await models.User.query().count('* as count').first();
      const adminUsers = await models.User.query()
        .where('is_admin', 1)
        .count('* as count')
        .first();
      const activeUsers = await models.User.query()
        .where('is_active', 1)
        .count('* as count')
        .first();
      
      // Get users created in the last 30 days
      const creationByDay = [];
      for (let i = 29; i >= 0; i--) {
        const date = subDays(new Date(), i);
        const formattedDate = date.toISOString().slice(0, 10);
        
        const created = await models.User.query()
          .where('created', 'like', `${formattedDate}%`)
          .count('* as count')
          .first();
        
        creationByDay.push({
          date: formattedDate,
          count: parseInt(created.count) || 0
        });
      }
      
      // Get active invites count
      const activeInvites = await models.Invite.query()
        .where('expires', '>', new Date().toISOString().slice(0, 19).replace('T', ' '))
        .count('* as count')
        .first();
      
      return res.json({
        users: {
          total: parseInt(totalUsers.count) || 0,
          admin: parseInt(adminUsers.count) || 0,
          active: parseInt(activeUsers.count) || 0
        },
        creationByDay,
        invites: {
          active: parseInt(activeInvites.count) || 0
        }
      });
    } catch (error) {
      console.error('Error fetching user stats:', error);
      return res.status(500).json({ error: 'Failed to fetch user statistics' });
    }
  }
}

module.exports = new StatsController(); 