import { Response } from 'express';
import { AuthenticatedRequest, ApiResponse, PaginatedResult } from '../types';

/**
 * Base controller with common response methods
 */
export abstract class BaseController {
  /**
   * Send success response
   */
  protected success<T>(res: Response, data: T, statusCode: number = 200): Response {
    const response: ApiResponse<T> = {
      success: true,
      data,
      meta: {
        timestamp: new Date().toISOString(),
      },
    };
    return res.status(statusCode).json(response);
  }

  /**
   * Send paginated response
   */
  protected paginated<T>(res: Response, result: PaginatedResult<T>): Response {
    const response: ApiResponse<T[]> & { pagination: PaginatedResult<T>['pagination'] } = {
      success: true,
      data: result.data,
      pagination: result.pagination,
      meta: {
        timestamp: new Date().toISOString(),
      },
    };
    return res.status(200).json(response);
  }

  /**
   * Send error response
   */
  protected error(
    res: Response,
    code: string,
    message: string,
    statusCode: number = 400,
    details?: any
  ): Response {
    const response: ApiResponse = {
      success: false,
      error: {
        code,
        message,
        ...(details && { details }),
      },
      meta: {
        timestamp: new Date().toISOString(),
      },
    };
    return res.status(statusCode).json(response);
  }

  /**
   * Send not found error
   */
  protected notFound(res: Response, resource: string = 'Resource'): Response {
    return this.error(res, 'NOT_FOUND', `${resource} not found`, 404);
  }

  /**
   * Send validation error
   */
  protected validationError(res: Response, details: any): Response {
    return this.error(res, 'VALIDATION_ERROR', 'Validation failed', 400, details);
  }

  /**
   * Send unauthorized error
   */
  protected unauthorized(res: Response, message: string = 'Unauthorized'): Response {
    return this.error(res, 'UNAUTHORIZED', message, 401);
  }

  /**
   * Send forbidden error
   */
  protected forbidden(res: Response, message: string = 'Forbidden'): Response {
    return this.error(res, 'FORBIDDEN', message, 403);
  }

  /**
   * Send conflict error
   */
  protected conflict(res: Response, message: string): Response {
    return this.error(res, 'CONFLICT', message, 409);
  }

  /**
   * Send internal error
   */
  protected internalError(res: Response, error?: Error): Response {
    console.error('Internal error:', error);
    return this.error(
      res,
      'INTERNAL_ERROR',
      'An unexpected error occurred',
      500,
      process.env.NODE_ENV === 'development' ? error?.message : undefined
    );
  }

  /**
   * Get tenant ID from request
   */
  protected getTenantId(req: AuthenticatedRequest): string {
    return req.tenant.tenantId;
  }

  /**
   * Get user ID from request
   */
  protected getUserId(req: AuthenticatedRequest): string {
    return req.user.userId;
  }

  /**
   * Get branch ID from request
   */
  protected getBranchId(req: AuthenticatedRequest): string | undefined {
    return req.branch?.branchId;
  }

  /**
   * Parse pagination from query
   */
  protected parsePagination(query: any): {
    page: number;
    limit: number;
    sortBy?: string;
    sortOrder?: 'ASC' | 'DESC';
  } {
    return {
      page: Math.max(1, parseInt(query.page) || 1),
      limit: Math.min(100, Math.max(1, parseInt(query.limit) || 20)),
      sortBy: query.sortBy,
      sortOrder: query.sortOrder?.toUpperCase() === 'ASC' ? 'ASC' : 'DESC',
    };
  }
}
