import UserClub from '../models/UserClub.js';
import Club from '../models/Club.js';
import User from '../models/User.js';

/**
 * Permission Service
 * Handles all permission-related logic
 */

// Default permissions for each role
const ROLE_PERMISSIONS = {
  admin: {
    diary: { read: true, write: true, delete: true },
    members: { read: true, write: true, delete: true },
    teams: { read: true, write: true, delete: true },
    schedule: { read: true, write: true, delete: true },
    tournaments: { read: true, write: true, delete: true },
    statistics: { read: true, write: true },
    settings: { read: true, write: true },
    permissions: { read: true, write: true }, // Can manage other users' permissions
    approvals: { read: true, write: true },
    mytischtennis_admin: { read: true, write: true },
    predefined_activities: { read: true, write: true, delete: true }
  },
  trainer: {
    diary: { read: true, write: true, delete: true },
    members: { read: true, write: true, delete: false },
    teams: { read: true, write: true, delete: false },
    schedule: { read: true, write: false, delete: false },
    tournaments: { read: true, write: true, delete: false },
    statistics: { read: true, write: false },
    settings: { read: false, write: false },
    permissions: { read: false, write: false },
    approvals: { read: false, write: false },
    mytischtennis_admin: { read: false, write: false },
    predefined_activities: { read: true, write: true, delete: true }
  },
  team_manager: {
    diary: { read: false, write: false, delete: false },
    members: { read: true, write: false, delete: false },
    teams: { read: true, write: true, delete: false },
    schedule: { read: true, write: true, delete: false },
    tournaments: { read: true, write: false, delete: false },
    statistics: { read: true, write: false },
    settings: { read: false, write: false },
    permissions: { read: false, write: false },
    approvals: { read: false, write: false },
    mytischtennis_admin: { read: false, write: false },
    predefined_activities: { read: false, write: false, delete: false }
  },
  tournament_manager: {
    diary: { read: false, write: false, delete: false },
    members: { read: true, write: false, delete: false },
    teams: { read: false, write: false, delete: false },
    schedule: { read: false, write: false, delete: false },
    tournaments: { read: true, write: true, delete: false },
    statistics: { read: true, write: false },
    settings: { read: false, write: false },
    permissions: { read: false, write: false },
    approvals: { read: false, write: false },
    mytischtennis_admin: { read: false, write: false },
    predefined_activities: { read: false, write: false, delete: false }
  },
  member: {
    diary: { read: false, write: false, delete: false },
    members: { read: false, write: false, delete: false },
    teams: { read: false, write: false, delete: false },
    schedule: { read: false, write: false, delete: false },
    tournaments: { read: false, write: false, delete: false },
    statistics: { read: true, write: false },
    settings: { read: false, write: false },
    permissions: { read: false, write: false },
    approvals: { read: false, write: false },
    mytischtennis_admin: { read: false, write: false },
    predefined_activities: { read: false, write: false, delete: false }
  }
};

class PermissionService {
  /**
   * Get user's permissions for a specific club
   */
  async getUserClubPermissions(userId, clubId) {
    const userClub = await UserClub.findOne({
      where: {
        userId,
        clubId,
        approved: true
      }
    });

    if (!userClub) {
      return null;
    }

    // If user is owner, they have full admin rights
    if (userClub.isOwner) {
      return {
        role: 'admin',
        isOwner: true,
        permissions: ROLE_PERMISSIONS.admin
      };
    }

    // Get role from database, fallback to 'member' if null/undefined
    const role = userClub.role || 'member';
    
    // Get role-based permissions
    const rolePermissions = ROLE_PERMISSIONS[role] || ROLE_PERMISSIONS.member;

    // Merge with custom permissions if any
    const customPermissions = userClub.permissions || {};
    const mergedPermissions = this.mergePermissions(rolePermissions, customPermissions);

    return {
      role: role,
      isOwner: false,
      permissions: mergedPermissions
    };
  }

  /**
   * Check if user has specific permission
   */
  async hasPermission(userId, clubId, resource, action) {
    const userPermissions = await this.getUserClubPermissions(userId, clubId);
    
    if (!userPermissions) {
      return false;
    }

    // Owner always has permission
    if (userPermissions.isOwner) {
      return true;
    }

    // MyTischtennis settings are accessible to all approved members
    if (resource === 'mytischtennis') {
      return true;
    }

    const resourcePermissions = userPermissions.permissions[resource];
    if (!resourcePermissions) {
      return false;
    }

    return resourcePermissions[action] === true;
  }

  /**
   * Set user role in club
   */
  async setUserRole(userId, clubId, role, updatedByUserId) {
    // Check if updater has permission
    const canManagePermissions = await this.hasPermission(updatedByUserId, clubId, 'permissions', 'write');
    if (!canManagePermissions) {
      throw new Error('Keine Berechtigung zum Ändern von Rollen');
    }

    // Check if target user is owner
    const targetUserClub = await UserClub.findOne({
      where: { userId, clubId }
    });

    if (!targetUserClub) {
      throw new Error('Benutzer ist kein Mitglied dieses Clubs');
    }

    if (targetUserClub.isOwner) {
      throw new Error('Die Rolle des Club-Erstellers kann nicht geändert werden');
    }

    // Validate role
    if (!ROLE_PERMISSIONS[role]) {
      throw new Error('Ungültige Rolle');
    }

    await targetUserClub.update({ role });

    return {
      success: true,
      message: 'Rolle erfolgreich aktualisiert'
    };
  }

  /**
   * Set custom permissions for user
   */
  async setCustomPermissions(userId, clubId, customPermissions, updatedByUserId) {
    // Check if updater has permission
    const canManagePermissions = await this.hasPermission(updatedByUserId, clubId, 'permissions', 'write');
    if (!canManagePermissions) {
      throw new Error('Keine Berechtigung zum Ändern von Berechtigungen');
    }

    // Check if target user is owner
    const targetUserClub = await UserClub.findOne({
      where: { userId, clubId }
    });

    if (!targetUserClub) {
      throw new Error('Benutzer ist kein Mitglied dieses Clubs');
    }

    if (targetUserClub.isOwner) {
      throw new Error('Die Berechtigungen des Club-Erstellers können nicht geändert werden');
    }

    await targetUserClub.update({ permissions: customPermissions });

    return {
      success: true,
      message: 'Berechtigungen erfolgreich aktualisiert'
    };
  }

  /**
   * Set user status (activate/deactivate)
   */
  async setUserStatus(userId, clubId, approved, updatedByUserId) {
    // Check if updater has permission
    const canManagePermissions = await this.hasPermission(updatedByUserId, clubId, 'permissions', 'write');
    if (!canManagePermissions) {
      throw new Error('Keine Berechtigung zum Ändern des Status');
    }

    // Check if target user is owner
    const targetUserClub = await UserClub.findOne({
      where: { userId, clubId }
    });

    if (!targetUserClub) {
      throw new Error('Benutzer ist kein Mitglied dieses Clubs');
    }

    if (targetUserClub.isOwner) {
      throw new Error('Der Status des Club-Erstellers kann nicht geändert werden');
    }

    await targetUserClub.update({ approved });

    return {
      success: true,
      message: approved ? 'Benutzer erfolgreich aktiviert' : 'Benutzer erfolgreich deaktiviert'
    };
  }

  /**
   * Get all club members with their permissions
   */
  async getClubMembersWithPermissions(clubId, requestingUserId) {
    // Check if requester has permission to read permissions
    const canReadPermissions = await this.hasPermission(requestingUserId, clubId, 'permissions', 'read');
    if (!canReadPermissions) {
      throw new Error('Keine Berechtigung zum Anzeigen von Berechtigungen');
    }

    const userClubs = await UserClub.findAll({
      where: {
        clubId
      },
      include: [{
        model: User,
        as: 'user',
        attributes: ['id', 'email']
      }]
    });

    return userClubs.map(uc => {
      // Parse permissions JSON string to object
      let parsedPermissions = null;
      if (uc.permissions) {
        try {
          parsedPermissions = typeof uc.permissions === 'string' 
            ? JSON.parse(uc.permissions) 
            : uc.permissions;
        } catch (err) {
          console.error('Error parsing permissions JSON:', err);
          parsedPermissions = null;
        }
      }

      return {
        userId: uc.userId,
        user: uc.user,
        role: uc.role,
        isOwner: uc.isOwner,
        approved: uc.approved,
        permissions: parsedPermissions,
        effectivePermissions: this.getEffectivePermissions(uc)
      };
    });
  }

  /**
   * Get effective permissions (role + custom)
   */
  getEffectivePermissions(userClub) {
    if (userClub.isOwner) {
      return ROLE_PERMISSIONS.admin;
    }

    const rolePermissions = ROLE_PERMISSIONS[userClub.role] || ROLE_PERMISSIONS.member;
    
    // Parse permissions JSON string to object
    let customPermissions = {};
    if (userClub.permissions) {
      try {
        customPermissions = typeof userClub.permissions === 'string' 
          ? JSON.parse(userClub.permissions) 
          : userClub.permissions;
      } catch (err) {
        console.error('Error parsing permissions JSON in getEffectivePermissions:', err);
        customPermissions = {};
      }
    }
    
    return this.mergePermissions(rolePermissions, customPermissions);
  }

  /**
   * Merge role permissions with custom permissions
   */
  mergePermissions(rolePermissions, customPermissions) {
    const merged = { ...rolePermissions };

    for (const resource in customPermissions) {
      if (!merged[resource]) {
        merged[resource] = {};
      }
      merged[resource] = {
        ...merged[resource],
        ...customPermissions[resource]
      };
    }

    return merged;
  }

  /**
   * Mark user as club owner (used when creating a club)
   */
  async setClubOwner(userId, clubId) {
    const userClub = await UserClub.findOne({
      where: { userId, clubId }
    });

    if (!userClub) {
      throw new Error('UserClub relationship not found');
    }

    await userClub.update({
      isOwner: true,
      role: 'admin',
      approved: true
    });
  }

  /**
   * Get all available roles
   */
  getAvailableRoles() {
    return [
      { value: 'admin', label: 'Administrator', description: 'Vollzugriff auf alle Funktionen' },
      { value: 'trainer', label: 'Trainer', description: 'Kann Trainingseinheiten, Mitglieder und Teams verwalten' },
      { value: 'team_manager', label: 'Mannschaftsführer', description: 'Kann Teams und Spielpläne verwalten' },
      { value: 'tournament_manager', label: 'Turnierleiter', description: 'Kann Turniere verwalten' },
      { value: 'member', label: 'Mitglied', description: 'Kann nur Trainings-Statistiken ansehen' }
    ];
  }

  /**
   * Get permission structure for frontend
   */
  getPermissionStructure() {
    return {
      diary: { label: 'Trainingstagebuch', actions: ['read', 'write', 'delete'] },
      members: { label: 'Mitglieder', actions: ['read', 'write', 'delete'] },
      teams: { label: 'Teams', actions: ['read', 'write', 'delete'] },
      schedule: { label: 'Spielpläne', actions: ['read', 'write', 'delete'] },
      tournaments: { label: 'Turniere', actions: ['read', 'write', 'delete'] },
      statistics: { label: 'Statistiken', actions: ['read', 'write'] },
      settings: { label: 'Einstellungen', actions: ['read', 'write'] },
      permissions: { label: 'Berechtigungsverwaltung', actions: ['read', 'write'] },
      approvals: { label: 'Freigaben (Mitgliedsanträge)', actions: ['read', 'write'] },
      mytischtennis_admin: { label: 'MyTischtennis Admin', actions: ['read', 'write'] },
      predefined_activities: { label: 'Vordefinierte Aktivitäten', actions: ['read', 'write', 'delete'] }
    };
  }
}

export default new PermissionService();

