import { Request, Response, NextFunction } from 'express';
import { CreateTransactionUseCase } from '../../application/use-cases/transaction/create-transaction.use-case';
import { GetTransactionsUseCase } from '../../application/use-cases/transaction/get-transactions.use-case';
import { GetTransactionByIdUseCase } from '../../application/use-cases/transaction/get-transaction-by-id.use-case';
import { UpdateTransactionUseCase } from '../../application/use-cases/transaction/update-transaction.use-case';
import { TransactionRateUseCase } from '../../application/use-cases/transaction/transaction-rate.use-case';
import {
  CreateTransactionInput,
  GetTransactionsInput,
  UpdateTransactionInput,
  TransactionRateInput,
} from '../../application/dto';

export class TransactionController {
  constructor(
    private readonly createTransactionUseCase: CreateTransactionUseCase,
    private readonly getTransactionsUseCase: GetTransactionsUseCase,
    private readonly getTransactionByIdUseCase: GetTransactionByIdUseCase,
    private readonly updateTransactionUseCase: UpdateTransactionUseCase,
    private readonly transactionRateUseCase: TransactionRateUseCase,
  ) {}

  create = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    try {
      const transaction = await this.createTransactionUseCase.execute(
        req.body as CreateTransactionInput,
      );
      res.status(201).json({ success: true, data: transaction });
    } catch (error) {
      next(error);
    }
  };

  getAll = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    try {
      const transactions = await this.getTransactionsUseCase.execute(
        req.query as unknown as GetTransactionsInput,
      );
      res.status(200).json({ success: true, data: transactions });
    } catch (error) {
      next(error);
    }
  };

  getById = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    try {
      const transaction = await this.getTransactionByIdUseCase.execute(req.params.id as string);
      res.status(200).json({ success: true, data: transaction });
    } catch (error) {
      next(error);
    }
  };

  update = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    try {
      const transaction = await this.updateTransactionUseCase.execute(
        req.params.id as string,
        req.body as UpdateTransactionInput,
      );
      res.status(200).json({ success: true, data: transaction });
    } catch (error) {
      next(error);
    }
  };

  rate = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    try {
      const rate = await this.transactionRateUseCase.execute(req.body as TransactionRateInput);
      res.status(200).json({ success: true, data: rate });
    } catch (error) {
      next(error);
    }
  };
}
