package com.magistr.app.controller;

import com.magistr.app.config.auth.RequireRoles;
import com.magistr.app.dto.ClassroomRequest;
import com.magistr.app.dto.ClassroomResponse;
import com.magistr.app.model.Classroom;
import com.magistr.app.model.Equipment;
import com.magistr.app.model.LifecycleEntity;
import com.magistr.app.model.Role;
import com.magistr.app.repository.ClassroomRepository;
import com.magistr.app.repository.EquipmentRepository;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.Optional;

@RestController
@RequestMapping("/api/classrooms")
@RequireRoles({Role.ADMIN, Role.EDUCATION_OFFICE})
public class ClassroomController {

    private final ClassroomRepository classroomRepository;
    private final EquipmentRepository equipmentRepository;

    public ClassroomController(ClassroomRepository classroomRepository, EquipmentRepository equipmentRepository) {
        this.classroomRepository = classroomRepository;
        this.equipmentRepository = equipmentRepository;
    }

    @GetMapping
    @RequireRoles({Role.ADMIN, Role.EDUCATION_OFFICE, Role.DEPARTMENT, Role.SCHEDULE_VIEWER})
    public List<ClassroomResponse> getAllClassrooms(@RequestParam(defaultValue = "false") boolean includeArchived) {
        List<Classroom> classrooms = includeArchived
                ? classroomRepository.findAll()
                : classroomRepository.findByStatusNot(LifecycleEntity.STATUS_ARCHIVED);
        return classrooms.stream()
                .map(this::mapToResponse)
                .toList();
    }

    @PostMapping
    public ResponseEntity<?> createClassroom(@RequestBody ClassroomRequest request) {
        if (request.getName() == null || request.getName().isBlank()) {
            return ResponseEntity.badRequest().body(Map.of("message", "Название аудитории обязательно"));
        }
        if (request.getCapacity() == null || request.getCapacity() <= 0) {
            return ResponseEntity.badRequest().body(Map.of("message", "Вместимость должна быть больше нуля"));
        }
        if (classroomRepository.findByName(request.getName().trim()).isPresent()) {
            return ResponseEntity.badRequest().body(Map.of("message", "Аудитория с таким названием уже существует"));
        }

        Classroom classroom = new Classroom();
        classroom.setName(request.getName().trim());
        classroom.setCapacity(request.getCapacity());
        classroom.setBuilding(cleanText(request.getBuilding()));
        classroom.setFloor(request.getFloor());
        classroom.setIsAvailable(request.getIsAvailable() != null ? request.getIsAvailable() : true);

        if (request.getEquipmentIds() != null && !request.getEquipmentIds().isEmpty()) {
            List<Equipment> equipments = equipmentRepository.findAllById(request.getEquipmentIds()).stream()
                    .filter(Equipment::isActiveRecord)
                    .toList();
            classroom.setEquipments(new java.util.HashSet<>(equipments));
        }

        classroomRepository.save(classroom);
        return ResponseEntity.ok(mapToResponse(classroom));
    }

    @PutMapping("/{id}")
    public ResponseEntity<?> updateClassroom(@PathVariable Long id, @RequestBody ClassroomRequest request) {
        Optional<Classroom> opt = classroomRepository.findById(id);
        if (opt.isEmpty()) {
            return ResponseEntity.notFound().build();
        }

        Classroom classroom = opt.get();

        if (request.getName() != null && !request.getName().isBlank()
                && !classroom.getName().equals(request.getName().trim())) {
            if (classroomRepository.findByName(request.getName().trim()).isPresent()) {
                return ResponseEntity.badRequest()
                        .body(Map.of("message", "Аудитория с таким названием уже существует"));
            }
            classroom.setName(request.getName().trim());
        }

        if (request.getCapacity() != null && request.getCapacity() > 0) {
            classroom.setCapacity(request.getCapacity());
        }

        if (request.getBuilding() != null) {
            classroom.setBuilding(cleanText(request.getBuilding()));
        }

        if (request.getFloor() != null) {
            classroom.setFloor(request.getFloor());
        }

        if (request.getIsAvailable() != null) {
            classroom.setIsAvailable(request.getIsAvailable());
        }

        if (request.getEquipmentIds() != null) {
            List<Equipment> equipments = equipmentRepository.findAllById(request.getEquipmentIds());
            equipments = equipments.stream()
                    .filter(Equipment::isActiveRecord)
                    .toList();
            classroom.setEquipments(new java.util.HashSet<>(equipments));
        }

        classroomRepository.save(classroom);
        return ResponseEntity.ok(mapToResponse(classroom));
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<?> deleteClassroom(@PathVariable Long id) {
        Optional<Classroom> classroomOpt = classroomRepository.findById(id);
        if (classroomOpt.isEmpty()) {
            return ResponseEntity.notFound().build();
        }
        Classroom classroom = classroomOpt.get();
        classroom.archive("Выведена из эксплуатации");
        classroom.setIsAvailable(false);
        classroomRepository.save(classroom);
        return ResponseEntity.ok(Map.of("message", "Аудитория выведена из эксплуатации"));
    }

    @PostMapping("/{id}/restore")
    public ResponseEntity<?> restoreClassroom(@PathVariable Long id) {
        Optional<Classroom> classroomOpt = classroomRepository.findById(id);
        if (classroomOpt.isEmpty()) {
            return ResponseEntity.notFound().build();
        }
        Classroom classroom = classroomOpt.get();
        classroom.restore();
        classroom.setIsAvailable(true);
        classroomRepository.save(classroom);
        return ResponseEntity.ok(mapToResponse(classroom));
    }

    private ClassroomResponse mapToResponse(Classroom c) {
        return new ClassroomResponse(c.getId(), c.getName(), c.getCapacity(), c.getBuilding(), c.getFloor(), c.getIsAvailable(),
                c.getStatus(), c.getArchivedAt(), c.getArchiveReason(),
                new java.util.ArrayList<>(c.getEquipments()));
    }

    private String cleanText(String value) {
        return value == null || value.isBlank() ? null : value.trim();
    }
}
