package com.magistr.app.controller;

import com.magistr.app.config.auth.RequireRoles;
import com.magistr.app.dto.CreateSubjectRequest;
import com.magistr.app.dto.SubjectResponse;
import com.magistr.app.model.LifecycleEntity;
import com.magistr.app.model.Role;
import com.magistr.app.model.Subject;
import com.magistr.app.repository.SubjectRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

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

@RestController
@RequestMapping("/api/subjects")
@RequireRoles({Role.ADMIN})
public class SubjectController {

    private static final Logger logger = LoggerFactory.getLogger(SubjectController.class);

    private final SubjectRepository subjectRepository;

    public SubjectController(SubjectRepository subjectRepository) {
        this.subjectRepository = subjectRepository;
    }

    @GetMapping
    @RequireRoles({Role.ADMIN, Role.EDUCATION_OFFICE, Role.DEPARTMENT, Role.SCHEDULE_VIEWER})
    public List<Subject> getAllSubjects(@RequestParam(defaultValue = "false") boolean includeArchived) {
        logger.info("Получен запрос на получение всех дисциплин");
        try {
            List<Subject> subjects = includeArchived
                    ? subjectRepository.findAll()
                    : subjectRepository.findByStatusNot(LifecycleEntity.STATUS_ARCHIVED);
            List<Subject> response = subjects.stream()
                    .map(s -> new Subject(
                            s.getId(),
                            s.getName(),
                            s.getCode(),
                            s.getDepartmentId()
                    ))
                    .toList();
            logger.info("Получено {} дисциплин", response.size());
            return response;
        } catch (Exception e) {
            logger.error("Ошибка при получении списка дисциплин: {}",  e.getMessage(), e);
            throw e;
        }
    }

    @GetMapping("/{departmentId}")
    @RequireRoles({Role.ADMIN, Role.EDUCATION_OFFICE, Role.DEPARTMENT, Role.SCHEDULE_VIEWER})
    public ResponseEntity<?> getSubjectsByDepartmentId(@PathVariable Long departmentId) {
        logger.info("Получен запрос на получение дисциплин для кафедры с ID - {}", departmentId);
        try{
            List<Subject> subjects = subjectRepository.findByDepartmentIdAndStatusNot(departmentId, LifecycleEntity.STATUS_ARCHIVED);

            if(subjects.isEmpty()){
                logger.info("Дисциплины для кафедры с ID - {} не найдены", departmentId);
                return ResponseEntity.status(HttpStatus.NOT_FOUND)
                        .body("Дисциплины для указанной кафедры не найдены");
            }

            logger.info("Найдено {} дисциплин для кафедры с ID - {}", subjects.size(), departmentId);
            return ResponseEntity.ok(subjects);
        } catch (Exception e) {
            logger.error("Произошла ошибка при получении списка дисциплин для кафедры с ID - {}", departmentId);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("Произошла ошибка при получении списка дисциплин");
        }
    }

    @PostMapping
    public ResponseEntity<?> createSubject(@RequestBody CreateSubjectRequest request) {
        logger.info("Получен запрос на создание дисциплины: name = {}, code = {}, departmentId = {}",
                request.getName(), request.getCode(), request.getDepartmentId());

        try {
            if (request.getName() == null || request.getName().isBlank()) {
                String errorMessage = "Название обязательно";
                logger.error("Ошибка валидации: {}", errorMessage);
                return ResponseEntity.badRequest().body(Map.of("message", errorMessage));
            }
            if (subjectRepository.findByNameIgnoreCase(request.getName().trim()).isPresent()) {
                String errorMessage = "Дисциплина с таким названием уже существует";
                logger.error("Ошибка валидации: {}", errorMessage);
                return ResponseEntity.badRequest().body(Map.of("message", errorMessage));
            }
            if (request.getCode() == null || request.getCode().isBlank()) {
                String errorMessage = "Код дисциплины обязателен";
                logger.error("Ошибка валидации: {}", errorMessage);
                return ResponseEntity.badRequest().body(Map.of("message", errorMessage));
            }
            if (request.getDepartmentId() == null || request.getDepartmentId() == 0) {
                String errorMessage = "ID кафедры не может быть равен 0 или пустым";
                logger.error("Ошибка валидации: {}", errorMessage);
                return ResponseEntity.badRequest().body(Map.of("message", errorMessage));
            }

            Subject subject = new Subject();
            subject.setName(request.getName());
            subject.setCode(request.getCode());
            subject.setDepartmentId(request.getDepartmentId());
            subjectRepository.save(subject);

            logger.info("Дисциплина успешно создана с ID: {}", subject.getId());

            return ResponseEntity.ok(
                    new SubjectResponse(
                            subject.getId(),
                            subject.getName(),
                            subject.getCode(),
                            subject.getDepartmentId()
                    )
            );
        } catch (Exception e) {
            logger.error("Ошибка при создании дисциплины", e);
            throw e;
        }
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<?> deleteSubject(@PathVariable Long id) {
        logger.info("Получен запрос на удаление дисциплины с ID: {}", id);
        Subject subject = subjectRepository.findById(id).orElse(null);
        if (subject == null) {
            logger.info("Дисциплина с ID - {} не найдена", id);
            return ResponseEntity.notFound().build();
        }
        subject.archive("Дисциплина архивирована");
        subjectRepository.save(subject);
        logger.info("Дисциплина с ID - {} успешно архивирована", id);
        return ResponseEntity.ok(Map.of("message", "Дисциплина архивирована"));
    }

    @PostMapping("/{id}/restore")
    @RequireRoles({Role.ADMIN})
    public ResponseEntity<?> restoreSubject(@PathVariable Long id) {
        Subject subject = subjectRepository.findById(id).orElse(null);
        if (subject == null) {
            return ResponseEntity.notFound().build();
        }
        subject.restore();
        subjectRepository.save(subject);
        return ResponseEntity.ok(new SubjectResponse(
                subject.getId(),
                subject.getName(),
                subject.getCode(),
                subject.getDepartmentId()
        ));
    }
}
