import { ApiValidationError } from "../../Models/Server.Error.model";
import {
    Body,
    Controller,
    Middlewares,
    Post,
    Response,
    Route,
    FormField,
    UploadedFile,
    SuccessResponse,
} from "tsoa";
import { ServicesService } from "./Services.Service";
import {
    IService,
    CreateServiceParams,
    UpdateServiceParams,
    PaginateServicesParams,
    PaginateServicesResults,
    FindServicesByCompanyParams,
    CompanyServiceView,
    FindServicesByIdParams,
    PublicServicesResults,
    SetPublishedStatusParams,
    FindServicesParams,
    ApplyDiscountParams,
    DeleteDiscountParams,
} from "../../Models/Services/Service.Interface";
import { authenticateMiddleware } from "../../middleware/authentication";
import { ApiVoidResult } from "../../Models/Api.VoidResult.type";
import { TextObjectFilterResult } from "../../Models/TextObjectFilter.model";

@Route("services/apply-discount")
@Middlewares(authenticateMiddleware)
export class ApplyDiscountServiceController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "Done")
    @Post()
    public async applyDiscount(
        @Body() requestBody: ApplyDiscountParams
    ): Promise<ApiVoidResult | ApiValidationError> {
        try {
            await new ServicesService().applyDiscount(requestBody);
            this.setStatus(200);
            return {
                success: true,
                message: "Done",
            };
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("services/delete-discount")
@Middlewares(authenticateMiddleware)
export class DeleteDiscountServiceController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "Done")
    @Post()
    public async applyDiscount(
        @Body() requestBody: DeleteDiscountParams
    ): Promise<ApiVoidResult | ApiValidationError> {
        try {
            await new ServicesService().deleteDiscount(requestBody);
            this.setStatus(200);
            return {
                success: true,
                message: "Done",
            };
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("services/set-published-status")
@Middlewares(authenticateMiddleware)
export class SetPublishedStatusServiceController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "Done")
    @Post()
    public async setPublishedStatus(
        @Body() requestBody: SetPublishedStatusParams
    ): Promise<ApiVoidResult | ApiValidationError> {
        try {
            await new ServicesService().setPublishedStatus(requestBody);
            this.setStatus(200);
            return {
                success: true,
                message: "Done",
            };
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("services/create")
@Middlewares(authenticateMiddleware)
export class CreateServiceController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "El empleado fue creado con exito")
    @Post()
    public async createService(
        @Body() requestBody: CreateServiceParams
    ): Promise<IService | ApiValidationError> {
        try {
            const service = await new ServicesService().createService(requestBody);
            this.setStatus(200);
            return service;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("services/update")
@Middlewares(authenticateMiddleware)
export class UpdateServiceController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "El servicio fue modificado con exito")
    @Post()
    public async updateService(
        @Body() requestBody: UpdateServiceParams
    ): Promise<ApiVoidResult | ApiValidationError> {
        try {
            await new ServicesService().updateService(requestBody);
            this.setStatus(200);
            return {
                success: true,
                message: "Done",
            };
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("services/paginate")
@Middlewares(authenticateMiddleware)
export class PaginateServiceController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "Done")
    @Post()
    public async paginateServices(
        @Body() requestBody: PaginateServicesParams
    ): Promise<PaginateServicesResults | ApiValidationError> {
        try {
            const services = await new ServicesService().paginateServices(requestBody);
            this.setStatus(200);
            return services;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("services/get-by-company")
export class FindServicesByCompanyController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "Done")
    @Post()
    public async findServicesByCompany(
        @Body() requestBody: FindServicesByCompanyParams
    ): Promise<CompanyServiceView[] | ApiValidationError> {
        try {
            const services = await new ServicesService().findByCompanyId(requestBody);
            this.setStatus(200);
            return services;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("services/get-by-id")
export class FindServicesByIdController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "Done")
    @Post()
    public async findServicesById(
        @Body() requestBody: FindServicesByIdParams
    ): Promise<CompanyServiceView | ApiValidationError> {
        try {
            const services = await new ServicesService().findById(requestBody);
            this.setStatus(200);
            return services;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("services/upload-image")
@Middlewares([authenticateMiddleware])
export class UploadServiceImageController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "El archivo fue cargado con exito")
    @Post()
    public async uploadImage(
        @FormField() companyId: string,
        @FormField() serviceId: string,
        @FormField() sessionUser: string,
        @UploadedFile() file: Express.Multer.File
    ): Promise<ApiVoidResult | ApiValidationError> {
        try {
            await new ServicesService().setServiceImage({
                companyId,
                serviceId,
                sessionUser,
                file,
            });
            this.setStatus(200);
            return {
                success: true,
                message: "Done",
            };
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("services/search")
export class PublicSearchServiceController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "Done")
    @Post()
    public async publicSearchServices(
        @Body() requestBody: PaginateServicesParams
    ): Promise<PublicServicesResults | ApiValidationError> {
        try {
            const services = await new ServicesService().publicServices(requestBody);
            this.setStatus(200);
            return services;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("services/filter-all")
export class AllOrganizationServicesController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "Done")
    @Post()
    public async allOrganizationServices(
        @Body() requestBody: FindServicesParams
    ): Promise<TextObjectFilterResult[] | ApiValidationError> {
        try {
            const services = await new ServicesService().textObjectFilter(requestBody);
            this.setStatus(200);
            return services;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}
