package com.example.web;

import java.io.IOException;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;

@WebServlet("/todos/*")
public class TodoServlet extends HttpServlet {
    private SessionTodoStore store(HttpServletRequest request) {
        HttpSession session=request.getSession();
        synchronized(session) {
            SessionTodoStore store=(SessionTodoStore)session.getAttribute("todoStore");
            if(store==null) { store=new SessionTodoStore(); session.setAttribute("todoStore",store); }
            return store;
        }
    }
    private String path(HttpServletRequest request) {
        return request.getPathInfo()==null ? "/" : request.getPathInfo();
    }
    private void form(HttpServletRequest req,HttpServletResponse res,String id,String title,
        boolean completed,String error) throws ServletException,IOException {
        req.setAttribute("id",id); req.setAttribute("title",title); req.setAttribute("completed",completed);
        req.setAttribute("error",error); req.setAttribute("formAction",id==null ? "/todos/create" : "/todos/update");
        req.getRequestDispatcher("/WEB-INF/views/form.jsp").forward(req,res);
    }
    private void redirect(HttpServletRequest req,HttpServletResponse res,String message) throws IOException {
        req.getSession().setAttribute("flash",message);
        res.sendRedirect(req.getContextPath()+"/todos");
    }
    @Override protected void doGet(HttpServletRequest req,HttpServletResponse res) throws ServletException,IOException {
        SessionTodoStore store=store(req);
        switch(path(req)) {
            case "/" -> {
                req.setAttribute("todos",store.list());
                HttpSession session=req.getSession();
                synchronized(session) {
                    Integer count=(Integer)session.getAttribute("listVisits");
                    session.setAttribute("listVisits",count==null ? 1 : count+1);
                    req.setAttribute("message",session.getAttribute("flash")); session.removeAttribute("flash");
                }
                req.getRequestDispatcher("/WEB-INF/views/list.jsp").forward(req,res);
            }
            case "/new" -> form(req,res,null,"",false,null);
            case "/edit" -> {
                Todo todo=store.find(req.getParameter("id")).orElse(null);
                if(todo==null) { res.sendError(404,"Todo not found"); return; }
                form(req,res,todo.getId(),todo.getTitle(),todo.isCompleted(),null);
            }
            default -> res.sendError(404,"Route not found");
        }
    }
    @Override protected void doPost(HttpServletRequest req,HttpServletResponse res) throws ServletException,IOException {
        String action=path(req);
        if(action.equals("/reset")) {
            req.getSession().invalidate(); res.sendRedirect(req.getContextPath()+"/todos"); return;
        }
        SessionTodoStore store=store(req);
        if(action.equals("/delete")) {
            if(!store.delete(req.getParameter("id"))) { res.sendError(404,"Todo not found"); return; }
            redirect(req,res,"Todo deleted"); return;
        }
        if(!action.equals("/create") && !action.equals("/update")) { res.sendError(404,"Route not found"); return; }
        String id=action.equals("/update") ? req.getParameter("id") : null;
        if(action.equals("/update") && store.find(id).isEmpty()) { res.sendError(404,"Todo not found"); return; }
        String title=req.getParameter("title"); title=title==null ? "" : title.strip();
        boolean completed="on".equals(req.getParameter("completed"));
        if(title.isBlank() || title.length()>120) {
            res.setStatus(400);
            form(req,res,id,title,completed,"Enter a title containing 1 to 120 characters."); return;
        }
        if(action.equals("/create")) store.create(title,completed);
        else if(store.update(id,title,completed).isEmpty()) { res.sendError(404,"Todo not found"); return; }
        redirect(req,res,action.equals("/create") ? "Todo created" : "Todo updated");
    }
}
