import { Request, Response, NextFunction } from 'express';
import { {{pascalCase model}}Repository } from '../repositories';
import { {{pascalCase model}}, Update{{pascalCase model}} } from '../DTOs';

class {{pascalCase model}}Controller {
  async create(req: Request, res: Response, next: NextFunction) {
    try {
      const {{camelCase model}}Data = {{pascalCase model}}.parse(req.body);
      const {{camelCase model}} = await {{pascalCase model}}Repository.create({{camelCase model}}Data);

      res.locals = {
        status: 201,
        message: '{{pascalCase model}} criado com sucesso!',
        data: {{camelCase model}},
      };

      return next();
    } catch (error) {
      return next(error);
    }
  }

  async read(req: Request, res: Response, next: NextFunction) {
    try {
      const { {{camelCase model1}}Id, {{camelCase model2}}Id } = req.params;
      const {{camelCase model}} = await {{pascalCase model}}Repository.findByIds({{camelCase model1}}Id, {{camelCase model2}}Id);

      if (!{{camelCase model}}) {
        return next({
          status: 404,
          message: '{{pascalCase model}} não encontrado.',
        });
      }

      res.locals = {
        status: 200,
        data: {{camelCase model}},
      };

      return next();
    } catch (error) {
      return next(error);
    }
  }

  async readAll(req: Request, res: Response, next: NextFunction) {
    try {
      const {{camelCase model}} = await {{pascalCase model}}Repository.findAll();
      res.locals = {
        status: 200,
        data: {{camelCase model}},
      };

      return next();
    } catch (error) {
      return next(error);
    }
  }

  async findBy{{pascalCase model1}}Id(req: Request, res: Response, next: NextFunction) {
    try {
      const { {{camelCase model1}}Id } = req.params;
      const {{camelCase model}} = await {{pascalCase model}}Repository.findBy{{pascalCase model1}}Id({{camelCase model1}}Id);

      res.locals = {
        status: 200,
        data: {{camelCase model}},
      };

      return next();
    } catch (error) {
      return next(error);
    }
  }

  async findBy{{pascalCase model2}}Id(req: Request, res: Response, next: NextFunction) {
    try {
      const { {{camelCase model2}}Id } = req.params;
      const {{camelCase model}} = await {{pascalCase model}}Repository.findBy{{pascalCase model2}}Id({{camelCase model2}}Id);

      res.locals = {
        status: 200,
        data: {{camelCase model}},
      };

      return next();
    } catch (error) {
      return next(error);
    }
  }

  async update(req: Request, res: Response, next: NextFunction) {
    try {
      const { {{camelCase model1}}Id, {{camelCase model2}}Id } = req.params;
      const {{camelCase model}}Data = Update{{pascalCase model}}.parse(req.body);

      const {{camelCase model}}Exists = await {{pascalCase model}}Repository.findByIds({{camelCase model1}}Id, {{camelCase model2}}Id);

      if (!{{camelCase model}}Exists) {
        return next({
          status: 404,
          message: '{{pascalCase model}} não encontrado.',
        });
      }

      const {{camelCase model}} = await {{pascalCase model}}Repository.update({{camelCase model1}}Id, {{camelCase model2}}Id, {{camelCase model}}Data);

      res.locals = {
        status: 200,
        data: {{camelCase model}},
        message: '{{pascalCase model}} atualizado com sucesso!',
      };

      return next();
    } catch (error) {
      return next(error);
    }
  }

  async delete(req: Request, res: Response, next: NextFunction) {
    try {
      const { {{camelCase model1}}Id, {{camelCase model2}}Id } = req.params;

      const {{camelCase model}}Exists = await {{pascalCase model}}Repository.findByIds({{camelCase model1}}Id, {{camelCase model2}}Id);

      if (!{{camelCase model}}Exists) {
        return next({
          status: 404,
          message: '{{pascalCase model}} não encontrado.',
        });
      }

      await {{pascalCase model}}Repository.delete({{camelCase model1}}Id, {{camelCase model2}}Id);

      res.locals = {
        status: 200,
        message: '{{pascalCase model}} deletado com sucesso.',
      };

      return next();
    } catch (error) {
      return next(error);
    }
  }
}

export default new {{pascalCase model}}Controller();
