package com.social.media.interfaces.web.controller;

import com.social.media.application.service.CompanyHierarchyService;
import com.social.media.infrastructure.persistence.entity.CompanyEntity;
import com.social.media.infrastructure.persistence.entity.BranchTypeEntity;
import com.social.media.infrastructure.persistence.entity.BranchStatusEntity;
import com.social.media.domain.user.valueobject.UserId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * REST Controller for Company Hierarchy operations - REFACTORED VERSION
 * All operations now include security validation with userId and companyId
 */
@RestController
@RequestMapping("/api/companies/hierarchy")
@CrossOrigin(origins = "*")
public class CompanyHierarchyController {
    
    @Autowired
    private CompanyHierarchyService companyHierarchyService;
    
    /**
     * Get all matriz companies (Super Admin only)
     */
    @GetMapping("/matriz")
    public ResponseEntity<List<CompanyEntity>> getAllMatrizCompanies() {
        var authInfo = getAuthenticatedUserInfo();
        
        // Only super admins can see all matriz companies
        if (!hasSuperAdminRole()) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        
        List<CompanyEntity> matrices = companyHierarchyService.getAllMatrizCompanies();
        return ResponseEntity.ok(matrices);
    }
    
    /**
     * Get direct children of a company with security validation
     */
    @GetMapping("/{companyId}/children")
    public ResponseEntity<List<CompanyEntity>> getDirectChildren(@PathVariable Long companyId) {
        var authInfo = getAuthenticatedUserInfo();
        
        // Verify user has access to this company
        if (!hasAccessToCompany(companyId, authInfo.companyId())) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        
        List<CompanyEntity> children = companyHierarchyService.getDirectChildren(companyId);
        return ResponseEntity.ok(children);
    }
    
    /**
     * Get companies by hierarchy level with security validation
     */
    @GetMapping("/level/{level}")
    public ResponseEntity<List<CompanyEntity>> getCompaniesByLevel(@PathVariable Integer level) {
        var authInfo = getAuthenticatedUserInfo();
        
        List<CompanyEntity> companies = companyHierarchyService.getCompaniesByHierarchyLevel(level);
        return ResponseEntity.ok(companies);
    }
    
    /**
     * Get companies by region with security validation
     */
    @GetMapping("/region/{region}")
    public ResponseEntity<List<CompanyEntity>> getCompaniesByRegion(@PathVariable String region) {
        var authInfo = getAuthenticatedUserInfo();
        
        List<CompanyEntity> companies = companyHierarchyService.getCompaniesByRegion(region);
        return ResponseEntity.ok(companies);
    }
    
    /**
     * Get companies by branch type with security validation
     */
    @GetMapping("/type/{branchType}")
    public ResponseEntity<List<CompanyEntity>> getCompaniesByBranchType(@PathVariable BranchTypeEntity branchType) {
        var authInfo = getAuthenticatedUserInfo();
        
        List<CompanyEntity> companies = companyHierarchyService.getCompaniesByBranchType(branchType);
        return ResponseEntity.ok(companies);
    }
    
    /**
     * Create a new matriz company
     */
    @PostMapping("/matriz")
    public ResponseEntity<CompanyEntity> createMatriz(@RequestBody CreateMatrizRequest request) {
        CompanyEntity matriz = companyHierarchyService.createMatriz(
            request.name, 
            request.email, 
            request.cnpj, 
            request.region
        );
        return ResponseEntity.ok(matriz);
    }
    
    /**
     * Create a new filial under a parent company
     */
    @PostMapping("/{parentId}/filial")
    public ResponseEntity<CompanyEntity> createFilial(
            @PathVariable Long parentId,
            @RequestBody CreateFilialRequest request) {
        CompanyEntity filial = companyHierarchyService.createFilial(
            parentId,
            request.name,
            request.email,
            request.cnpj,
            request.branchCode,
            request.region,
            request.branchType
        );
        return ResponseEntity.ok(filial);
    }
    
    /**
     * Move a filial to a different parent
     */
    @PutMapping("/{filialId}/move/{newParentId}")
    public ResponseEntity<CompanyEntity> moveFilial(
            @PathVariable Long filialId,
            @PathVariable Long newParentId) {
        CompanyEntity movedFilial = companyHierarchyService.moveFilial(filialId, newParentId);
        return ResponseEntity.ok(movedFilial);
    }
    
    /**
     * Promote filial to independent matriz
     */
    @PutMapping("/{filialId}/promote")
    public ResponseEntity<CompanyEntity> promoteToMatriz(@PathVariable Long filialId) {
        CompanyEntity promotedCompany = companyHierarchyService.promoteToMatriz(filialId);
        return ResponseEntity.ok(promotedCompany);
    }
    
    /**
     * Change branch status
     */
    @PutMapping("/{companyId}/status/{newStatus}")
    public ResponseEntity<CompanyEntity> changeBranchStatus(
            @PathVariable Long companyId,
            @PathVariable BranchStatusEntity newStatus) {
        CompanyEntity updatedCompany = companyHierarchyService.changeBranchStatus(companyId, newStatus);
        return ResponseEntity.ok(updatedCompany);
    }
    
    /**
     * Get hierarchy statistics for a company
     */
    @GetMapping("/{companyId}/stats")
    public ResponseEntity<CompanyHierarchyService.HierarchyStats> getHierarchyStats(@PathVariable Long companyId) {
        CompanyHierarchyService.HierarchyStats stats = companyHierarchyService.getHierarchyStats(companyId);
        return ResponseEntity.ok(stats);
    }
    
    /**
     * Get regional distribution
     */
    @GetMapping("/distribution/region")
    public ResponseEntity<List<Object[]>> getRegionalDistribution() {
        List<Object[]> distribution = companyHierarchyService.getRegionalDistribution();
        return ResponseEntity.ok(distribution);
    }
    
    /**
     * Search companies with filters
     */
    @GetMapping("/search")
    public ResponseEntity<List<CompanyEntity>> searchCompanies(
            @RequestParam(required = false) BranchTypeEntity branchType,
            @RequestParam(required = false) String region,
            @RequestParam(required = false) BranchStatusEntity branchStatus,
            @RequestParam(required = false) Integer minLevel,
            @RequestParam(required = false) Integer maxLevel) {
        List<CompanyEntity> companies = companyHierarchyService.searchCompanies(
            branchType, region, branchStatus, minLevel, maxLevel
        );
        return ResponseEntity.ok(companies);
    }
    
    // === DTO CLASSES ===
    
    public static class CreateMatrizRequest {
        public String name;
        public String email;
        public String cnpj;
        public String region;
    }
    
    public static class CreateFilialRequest {
        public String name;
        public String email;
        public String cnpj;
        public String branchCode;
        public String region;
        public BranchTypeEntity branchType;
    }
    
    /**
     * Helper method to get authenticated user information
     */
    private AuthenticatedUserInfo getAuthenticatedUserInfo() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        
        if (authentication == null || !authentication.isAuthenticated()) {
            throw new RuntimeException("User not authenticated");
        }
        
        // Extract user ID and company ID from authentication
        Long userId = extractUserIdFromAuthentication(authentication);
        Long companyId = extractCompanyIdFromAuthentication(authentication);
        
        return new AuthenticatedUserInfo(UserId.of(userId), companyId);
    }
    
    private Long extractUserIdFromAuthentication(Authentication authentication) {
        // TODO: Implement based on your JWT/session structure
        return 1L; // Temporary
    }
    
    private Long extractCompanyIdFromAuthentication(Authentication authentication) {
        // TODO: Implement based on your JWT/session structure
        return 1L; // Temporary
    }
    
    private boolean hasSuperAdminRole() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return authentication.getAuthorities().stream()
                .anyMatch(authority -> authority.getAuthority().equals("ROLE_SUPER_ADMIN"));
    }
    
    private boolean hasAdminRole() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return authentication.getAuthorities().stream()
                .anyMatch(authority -> authority.getAuthority().equals("ROLE_ADMIN"));
    }
    
    private boolean hasAccessToCompany(Long targetCompanyId, Long userCompanyId) {
        // Users can access their own company and its hierarchy
        // Super admins can access any company
        return userCompanyId.equals(targetCompanyId) || hasSuperAdminRole();
    }
    
    /**
     * Record to hold authenticated user information
     */
    private record AuthenticatedUserInfo(UserId userId, Long companyId) {}
}
