package com.example.todolist.controller;

import java.nio.charset.StandardCharsets;
import java.util.List;

import jakarta.servlet.http.HttpSession;

import org.springframework.core.io.Resource;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import com.example.todolist.entity.Todo;
import com.example.todolist.exception.ForbiddenException;
import com.example.todolist.repository.AttachedFileRepository;
import com.example.todolist.repository.TodoRepository;
import com.example.todolist.service.DownloadService;
import com.example.todolist.service.ExcelService;
import com.example.todolist.service.FileDownload;
import com.example.todolist.service.PdfService;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
public class DownloadController {
    private final DownloadService downloadService;
    private final TodoRepository todoRepository;
    private final PdfService pdfService;
    private final ExcelService excelService;
    private final HttpSession session;
    private final AttachedFileRepository attachedFileRepository;

    private static final MediaType MEDIA_TYPE_XLSX = MediaType.parseMediaType(
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

    // 添付ファイルのダウンロード処理
    @GetMapping("/todo/af/download/{afId}")
    public ResponseEntity<Resource> downloadAttachedFile(@PathVariable int afId) {
        // 添付ファイルが存在するか
        if (!attachedFileRepository.existsById(afId)) {
            throw new ForbiddenException("msg.e.attached_file_not_found");
        }
        // 所有者チェック
        Integer accountId = (Integer) session.getAttribute("accountId");
        if (!attachedFileRepository.existsByIdAndOwnerIdNative(afId, accountId)) {
            throw new ForbiddenException("msg.e.attached_file_forbidden");
        }

        FileDownload r = downloadService.loadAsResource(afId);
        ContentDisposition cd = r.isInline()
                // 別タブ表示の場合
                ? ContentDisposition
                        .inline().filename(r.getFileName(), StandardCharsets.UTF_8).build()
                // ダウンロードの場合
                : ContentDisposition
                        .attachment().filename(r.getFileName(), StandardCharsets.UTF_8).build();

        return ResponseEntity.ok()
                .contentType(r.getContentType())
                .header(HttpHeaders.CONTENT_DISPOSITION, cd.toString())
                .contentLength(r.getLength())
                .body(r.getResource());
    }

    // PDF生成
    @GetMapping("/todo/pdf")
    public ResponseEntity<byte[]> downloadTodoPdf() {
        Integer accountId = (Integer) session.getAttribute("accountId");
        List<Todo> todoList = todoRepository.findByOwnerIdOrderById(accountId);
        ;
        byte[] pdf = pdfService.createTodoPdf(todoList);

        String fileName = "Todo一覧表.pdf";

        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_PDF)
                .header(HttpHeaders.CONTENT_DISPOSITION,
                        ContentDisposition.inline()
                                .filename(fileName, StandardCharsets.UTF_8)
                                .build()
                                .toString())
                .contentLength(pdf.length)
                .body(pdf);
    }

    // Excel生成
    @GetMapping("/todo/excel")
    public ResponseEntity<byte[]> downloadTodoExcel() {
        Integer accountId = (Integer) session.getAttribute("accountId");
        List<Todo> todoList = todoRepository.findByOwnerIdOrderById(accountId);
        ;
        byte[] bytes = excelService.createTodoExcel(todoList);

        String fileName = "ToDoList.xlsx";

        return ResponseEntity.ok()
                .contentType(MEDIA_TYPE_XLSX)
                .header(HttpHeaders.CONTENT_DISPOSITION,
                        ContentDisposition.attachment()
                                .filename(fileName, StandardCharsets.UTF_8)
                                .build()
                                .toString())
                .contentLength(bytes.length)
                .body(bytes);
    }

}
