import { Body, Controller, Post, Route, SuccessResponse, Middlewares } from "tsoa";
import { authenticateMiddleware } from "../../middleware/authentication";
import { ApiValidationError } from "../../Models/Server.Error.model";
import {
    CreatePaymentParams,
    DeletePaymentParams,
    FindPaymentsParams,
    GetAppointmentPaymentsParams,
    IPayment,
    MarkAsPayedParams,
    PaginateNotPayedAppointmentsParams,
    PaginateNotPayedAppointmentsResult,
    NotPayedReportResult, PaymentsReportResult,
    PaginatePaymentsViewParams,
    PaginatePaymentsViewResults,
} from "../../Models/Payments/Payments.Interface";
import { PaymentsService } from "./Payments.Service";
import { ApiVoidResult } from "../../Models/Api.VoidResult.type";

@Route("payments/appointment")
@Middlewares(authenticateMiddleware)
export class AppointmentPaymentsController extends Controller {
    @SuccessResponse(200, "Done")
    @Post()
    public async getAppointmentPayments(
        @Body() requestBody: GetAppointmentPaymentsParams
    ): Promise<IPayment[] | ApiValidationError> {
        try {
            const payments = await new PaymentsService().getAppointmentPayments(requestBody);
            this.setStatus(200);
            return payments;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("payments/create")
@Middlewares(authenticateMiddleware)
export class CreatePaymentController extends Controller {
    @SuccessResponse(200, "Done")
    @Post()
    public async createPayment(
        @Body() requestBody: CreatePaymentParams
    ): Promise<IPayment | ApiValidationError> {
        try {
            const payment = await new PaymentsService().createPayment(requestBody);
            this.setStatus(200);
            return payment;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("payments/delete")
@Middlewares(authenticateMiddleware)
export class DeletePaymentController extends Controller {
    @SuccessResponse(200, "Done")
    @Post()
    public async deletePayment(
        @Body() requestBody: DeletePaymentParams
    ): Promise<ApiVoidResult | ApiValidationError> {
        try {
            await new PaymentsService().deletePayment(requestBody);
            this.setStatus(200);
            return {
                success: true,
                message: "",
            };
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("payments/mark-as-payed")
@Middlewares(authenticateMiddleware)
export class MarkAsPayedController extends Controller {
    @SuccessResponse(200, "Done")
    @Post()
    public async markAsPayed(
        @Body() requestBody: MarkAsPayedParams
    ): Promise<ApiVoidResult | ApiValidationError> {
        try {
            await new PaymentsService().markAsPayed(requestBody);
            this.setStatus(200);
            return {
                success: true,
                message: "",
            };
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("payments/paginated-view-total")
@Middlewares(authenticateMiddleware)
export class PaginatedPaymentsViewTotalController extends Controller {
    @SuccessResponse(200, "Done")
    @Post()
    public async paginatedPaymentsViewTotal(
        @Body() requestBody: FindPaymentsParams
    ): Promise<number | ApiValidationError> {
        try {
            const payment = await new PaymentsService().paginatedPaymentsViewTotal(requestBody);
            this.setStatus(200);
            return payment;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("payments/paginate-view")
@Middlewares(authenticateMiddleware)
export class PaginatePaymentsViewController extends Controller {
    @SuccessResponse(200, "Done")
    @Post()
    public async paginatePaymentsView(
        @Body() requestBody: PaginatePaymentsViewParams
    ): Promise<PaginatePaymentsViewResults | ApiValidationError> {
        try {
            const payment = await new PaymentsService().paginatePaymentsView(requestBody);
            this.setStatus(200);
            return payment;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("payments/not-payed")
@Middlewares(authenticateMiddleware)
export class PaginateNotPayedAppointmentsController extends Controller {
    @SuccessResponse(200, "Done")
    @Post()
    public async paginateNotPayedAppointments(
        @Body() requestBody: PaginateNotPayedAppointmentsParams
    ): Promise<PaginateNotPayedAppointmentsResult | ApiValidationError> {
        try {
            const payment = await new PaymentsService().paginateNotPayedAppointments(requestBody);
            this.setStatus(200);
            return payment;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("payments/not-payed-total")
@Middlewares(authenticateMiddleware)
export class PaginateNotPayedAppointmentsTotalController extends Controller {
    @SuccessResponse(200, "Done")
    @Post()
    public async paginateNotPayedAppointmentsTotal(
        @Body() requestBody: FindPaymentsParams
    ): Promise<number | ApiValidationError> {
        try {
            const payment = await new PaymentsService().paginatedNotPayedAppiontmentsTotal(
                requestBody
            );
            this.setStatus(200);
            return payment;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("payments/pay-not-payed")
@Middlewares(authenticateMiddleware)
export class PayNotPayedAppointmentsTotalController extends Controller {
    @SuccessResponse(200, "Done")
    @Post()
    public async payNotPayedAppointmentsTotal(
        @Body() requestBody: FindPaymentsParams
    ): Promise<ApiVoidResult | ApiValidationError> {
        try {
            await new PaymentsService().payNotPayedAppiontments(requestBody);
            this.setStatus(200);
            return {
                success: true,
                message: "",
            };
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}


@Route("payments/get-not-payed-report")
@Middlewares(authenticateMiddleware)
export class GetNotPayedReportController extends Controller {
    @SuccessResponse(200, "Done")
    @Post()
    public async getNotPayedReport(
        @Body() requestBody: FindPaymentsParams
    ): Promise<NotPayedReportResult | ApiValidationError> {
        try {
            const report = await new PaymentsService().getNotPayedReport(requestBody);
            this.setStatus(200);
            return report;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("payments/get-payments-report")
@Middlewares(authenticateMiddleware)
export class GetPaymentsReportController extends Controller {
    @SuccessResponse(200, "Done")
    @Post()
    public async getPaymentsReport(
        @Body() requestBody: FindPaymentsParams
    ): Promise<PaymentsReportResult | ApiValidationError> {
        try {
            const report = await new PaymentsService().getPaymentsReport(requestBody);
            this.setStatus(200);
            return report;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}
