package com.petshop.backend.controller;

import com.petshop.backend.dto.common.DropdownOption;
import com.petshop.backend.entity.User;
import com.petshop.backend.repository.*;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/v1/dropdowns")
public class DropdownController {

    private final PetRepository petRepository;
    private final ServiceRepository serviceRepository;
    private final ProductRepository productRepository;
    private final CategoryRepository categoryRepository;
    private final StoreRepository storeRepository;
    private final SupplierRepository supplierRepository;
    private final UserRepository userRepository;
    private final AdoptionRepository adoptionRepository;

    public DropdownController(PetRepository petRepository,
                              ServiceRepository serviceRepository, ProductRepository productRepository,
                              CategoryRepository categoryRepository, StoreRepository storeRepository,
                              SupplierRepository supplierRepository,
                              UserRepository userRepository,
                              AdoptionRepository adoptionRepository) {
        this.petRepository = petRepository;
        this.serviceRepository = serviceRepository;
        this.productRepository = productRepository;
        this.categoryRepository = categoryRepository;
        this.storeRepository = storeRepository;
        this.supplierRepository = supplierRepository;
        this.userRepository = userRepository;
        this.adoptionRepository = adoptionRepository;
    }

    @GetMapping("/pets")
    public ResponseEntity<List<DropdownOption>> getPets(@RequestParam(required = false) Long storeId) {
        List<DropdownOption> pets = petRepository.findAll().stream()
                .filter(p -> storeId == null || (p.getStore() != null && p.getStore().getStoreId().equals(storeId)))
                .map(p -> new DropdownOption(p.getPetId(), p.getPetName()))
                .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER))
                .collect(Collectors.toList());
        return ResponseEntity.ok(pets);
    }

    @GetMapping("/adoption-pets")
    @PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
    public ResponseEntity<List<DropdownOption>> getAdoptionPets(@RequestParam(required = false) Long storeId) {
        return ResponseEntity.ok(
                petRepository.findAdoptablePetsByStore(storeId).stream()
                        .map(p -> new DropdownOption(p.getPetId(), p.getPetName()))
                        .collect(Collectors.toList())
        );
    }

    @GetMapping("/customers")
    @PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
    public ResponseEntity<List<DropdownOption>> getCustomers() {
        return ResponseEntity.ok(
            userRepository.findByRoleAndActiveTrue(User.Role.CUSTOMER).stream()
                .map(u -> new DropdownOption(u.getId(), u.getFirstName() + " " + u.getLastName()))
                .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER))
                .collect(Collectors.toList())
        );
    }

    @GetMapping("/appointment-customers")
    @PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
    public ResponseEntity<List<DropdownOption>> getAppointmentCustomers() {
        Set<Long> ownersWithPets = petRepository.findAll().stream()
                .filter(p -> p.getOwner() != null)
                .map(p -> p.getOwner().getId())
                .collect(Collectors.toSet());
        Set<Long> customersWithAdoptions = adoptionRepository.findAll().stream()
                .filter(a -> "Completed".equalsIgnoreCase(a.getAdoptionStatus()))
                .map(a -> a.getCustomer().getId())
                .collect(Collectors.toSet());
        Set<Long> customersWithPets = new HashSet<>(ownersWithPets);
        customersWithPets.addAll(customersWithAdoptions);
        return ResponseEntity.ok(
                userRepository.findByRoleAndActiveTrue(User.Role.CUSTOMER).stream()
                        .filter(u -> customersWithPets.contains(u.getId()))
                        .map(u -> new DropdownOption(u.getId(), u.getFirstName() + " " + u.getLastName()))
                        .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER))
                        .collect(Collectors.toList())
        );
    }

    @GetMapping("/services")
    public ResponseEntity<List<DropdownOption>> getServices() {
        return ResponseEntity.ok(
            serviceRepository.findAll().stream()
                .map(s -> new DropdownOption(s.getServiceId(), s.getServiceName()))
                .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER))
                .collect(Collectors.toList())
        );
    }

    @GetMapping("/products")
    public ResponseEntity<List<DropdownOption>> getProducts() {
        return ResponseEntity.ok(
            productRepository.findAll().stream()
                .map(p -> new DropdownOption(p.getProdId(), p.getProdName()))
                .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER))
                .collect(Collectors.toList())
        );
    }

    @GetMapping("/categories")
    public ResponseEntity<List<DropdownOption>> getCategories() {
        return ResponseEntity.ok(
            categoryRepository.findAll().stream()
                .map(c -> new DropdownOption(c.getCategoryId(), c.getCategoryName()))
                .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER))
                .collect(Collectors.toList())
        );
    }

    @GetMapping("/product-categories")
    public ResponseEntity<List<DropdownOption>> getProductCategories() {
        return ResponseEntity.ok(
            categoryRepository.findAll().stream()
                .filter(c -> "product".equalsIgnoreCase(c.getCategoryType()))
                .map(c -> new DropdownOption(c.getCategoryId(), c.getCategoryName()))
                .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER))
                .collect(Collectors.toList())
        );
    }

    @GetMapping("/pet-species")
    public ResponseEntity<List<DropdownOption>> getPetSpecies() {
        return ResponseEntity.ok(
            petRepository.findAll().stream()
                .map(p -> p.getPetSpecies())
                .filter(species -> species != null && !species.isBlank())
                .distinct()
                .sorted(String.CASE_INSENSITIVE_ORDER)
                .map(species -> new DropdownOption(null, species))
                .collect(Collectors.toList())
        );
    }

    @GetMapping("/pet-breeds")
    public ResponseEntity<List<DropdownOption>> getPetBreeds(@RequestParam(required = false) String species) {
        if (species == null || species.isBlank()) {

            return ResponseEntity.ok(java.util.Collections.emptyList());
        }
        
        return ResponseEntity.ok(
            petRepository.findAll().stream()
                .filter(p -> species.equalsIgnoreCase(p.getPetSpecies()))
                .map(p -> p.getPetBreed())
                .filter(breed -> breed != null && !breed.isBlank())
                .distinct()
                .sorted(String.CASE_INSENSITIVE_ORDER)
                .map(breed -> new DropdownOption(null, breed))
                .collect(Collectors.toList())
        );
    }

    @GetMapping("/stores")
    public ResponseEntity<List<DropdownOption>> getStores() {
        return ResponseEntity.ok(
            storeRepository.findAll().stream()
                .map(s -> new DropdownOption(s.getStoreId(), s.getStoreName()))
                .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER))
                .collect(Collectors.toList())
        );
    }

    @GetMapping({"/stores/{storeId}/employees", "/employees"})
    @PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
    public ResponseEntity<List<DropdownOption>> getStoreEmployees(@PathVariable(required = false) Long storeId) {
        List<User> employees;
        if (storeId == null || storeId == 0) {
            employees = userRepository.findByRoleAndActiveTrue(User.Role.STAFF);
        } else {
            employees = userRepository.findByPrimaryStoreStoreIdAndRoleAndActiveTrue(storeId, User.Role.STAFF);
        }
        return ResponseEntity.ok(
                employees.stream()
                        .map(u -> new DropdownOption(u.getId(), u.getFirstName() + " " + u.getLastName()))
                        .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER))
                        .collect(Collectors.toList())
        );
    }

    @GetMapping("/customers/{customerId}/pets")
    @PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
    public ResponseEntity<List<DropdownOption>> getCustomerPets(@PathVariable Long customerId) {
        Set<Long> seen = new HashSet<>();
        List<DropdownOption> pets = new java.util.ArrayList<>();
        petRepository.findAllByOwner_IdOrderByPetNameAsc(customerId).stream()
                .map(p -> new DropdownOption(p.getPetId(), p.getPetName()))
                .forEach(o -> { if (seen.add(o.getId())) pets.add(o); });
        adoptionRepository.findByCustomer_IdAndAdoptionStatusIgnoreCase(customerId, "Completed").stream()
                .map(a -> new DropdownOption(a.getPet().getPetId(), a.getPet().getPetName()))
                .forEach(o -> { if (seen.add(o.getId())) pets.add(o); });
        pets.sort(java.util.Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER));
        return ResponseEntity.ok(pets);
    }

    @GetMapping("/suppliers")
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseEntity<List<DropdownOption>> getSuppliers() {
        return ResponseEntity.ok(
            supplierRepository.findAll().stream()
                .map(s -> new DropdownOption(s.getSupId(), s.getSupCompany()))
                .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER))
                .collect(Collectors.toList())
        );
    }
}
