import client from 'prom-client';
import { env } from '../config/env';

const register = new client.Registry();

register.setDefaultLabels({
  app: 'changemaker-v2-api',
  instance: env.INSTANCE_LABEL || env.DOMAIN || 'unknown',
});

client.collectDefaultMetrics({ register });

// --- HTTP Metrics (existing) ---

export const httpRequestDuration = new client.Histogram({
  name: 'http_request_duration_seconds',
  help: 'Duration of HTTP requests in seconds',
  labelNames: ['method', 'route', 'status_code'],
  buckets: [0.01, 0.05, 0.1, 0.3, 0.5, 1, 3, 5, 10],
  registers: [register],
});

export const httpRequestsTotal = new client.Counter({
  name: 'http_requests_total',
  help: 'Total number of HTTP requests',
  labelNames: ['method', 'route', 'status_code'],
  registers: [register],
});

// --- Email Metrics ---

export const emailsSentTotal = new client.Counter({
  name: 'cm_emails_sent_total',
  help: 'Total campaign emails sent successfully',
  labelNames: ['campaign_id'],
  registers: [register],
});

export const emailsFailedTotal = new client.Counter({
  name: 'cm_emails_failed_total',
  help: 'Total campaign emails that failed to send',
  labelNames: ['campaign_id', 'error_type'],
  registers: [register],
});

export const emailQueueSize = new client.Gauge({
  name: 'cm_email_queue_size',
  help: 'Current email queue size (waiting + active)',
  registers: [register],
});

export const emailSendDuration = new client.Histogram({
  name: 'cm_email_send_duration_seconds',
  help: 'Duration of individual email sends',
  buckets: [0.1, 0.5, 1, 2, 5, 10, 30],
  registers: [register],
});

// --- Auth Metrics ---

export const loginAttemptsTotal = new client.Counter({
  name: 'cm_login_attempts_total',
  help: 'Total login attempts',
  labelNames: ['status'],
  registers: [register],
});

export const activeSessions = new client.Gauge({
  name: 'cm_active_sessions',
  help: 'Number of active refresh tokens (approximate session count)',
  registers: [register],
});

// --- Campaign / Influence Metrics ---

export const campaignEmailsTotal = new client.Counter({
  name: 'cm_campaign_emails_total',
  help: 'Total campaign emails created (SMTP + mailto)',
  labelNames: ['campaign_id'],
  registers: [register],
});

export const responseSubmissionsTotal = new client.Counter({
  name: 'cm_response_submissions_total',
  help: 'Total response submissions from public',
  registers: [register],
});

// --- Canvass / Map Metrics ---

export const canvassVisitsTotal = new client.Counter({
  name: 'cm_canvass_visits_total',
  help: 'Total canvass visits recorded',
  labelNames: ['outcome'],
  registers: [register],
});

export const activeCanvassSessions = new client.Gauge({
  name: 'cm_active_canvass_sessions',
  help: 'Number of active canvass sessions',
  registers: [register],
});

export const shiftSignupsTotal = new client.Counter({
  name: 'cm_shift_signups_total',
  help: 'Total shift signups',
  registers: [register],
});

// --- Location Query Metrics ---

export const locationQueryDuration = new client.Histogram({
  name: 'cm_map_location_query_duration_seconds',
  help: 'Duration of location queries',
  labelNames: ['endpoint', 'has_bounds'],
  buckets: [0.01, 0.05, 0.1, 0.2, 0.5, 1, 2, 5],
  registers: [register],
});

export const locationQueryCount = new client.Counter({
  name: 'cm_map_location_query_count_total',
  help: 'Total location queries',
  labelNames: ['endpoint', 'has_bounds'],
  registers: [register],
});

export const locationResultCount = new client.Histogram({
  name: 'cm_map_location_result_count',
  help: 'Number of locations returned per query',
  labelNames: ['endpoint'],
  buckets: [10, 50, 100, 500, 1000, 5000, 10000],
  registers: [register],
});

// --- Geocoding Metrics ---

export const cm_geocode_cache_hits = new client.Counter({
  name: 'cm_geocode_cache_hits_total',
  help: 'Total geocoding cache hits',
  registers: [register],
});

export const cm_geocode_cache_misses = new client.Counter({
  name: 'cm_geocode_cache_misses_total',
  help: 'Total geocoding cache misses',
  registers: [register],
});

export const cm_geocode_requests_total = new client.Counter({
  name: 'cm_geocode_requests_total',
  help: 'Total geocoding requests',
  labelNames: ['provider', 'status'],
  registers: [register],
});

export const cm_geocode_duration = new client.Histogram({
  name: 'cm_geocode_duration_seconds',
  help: 'Duration of geocoding requests',
  labelNames: ['provider'],
  buckets: [0.1, 0.5, 1, 2, 5, 10, 30],
  registers: [register],
});

// --- Email Template Metrics ---

export const emailTemplatesUpdated = new client.Counter({
  name: 'cm_email_templates_updated_total',
  help: 'Email templates updated',
  labelNames: ['template_key', 'user_role'],
  registers: [register],
});

export const emailTestSent = new client.Counter({
  name: 'cm_email_test_sent_total',
  help: 'Test emails sent',
  labelNames: ['template_key', 'success'],
  registers: [register],
});

export const emailTemplateRollback = new client.Counter({
  name: 'cm_email_template_rollback_total',
  help: 'Template rollbacks',
  labelNames: ['template_key'],
  registers: [register],
});

export const emailTemplateCacheHit = new client.Counter({
  name: 'cm_email_template_cache_hit_total',
  help: 'Template cache hits',
  labelNames: ['template_key'],
  registers: [register],
});

export const emailTemplateCacheMiss = new client.Counter({
  name: 'cm_email_template_cache_miss_total',
  help: 'Template cache misses',
  labelNames: ['template_key'],
  registers: [register],
});

// --- Docs Editor Metrics ---

export const cm_docs_cache_hits = new client.Counter({
  name: 'cm_docs_cache_hits_total',
  help: 'Documentation cache hits',
  labelNames: ['type'], // 'tree' or 'file'
  registers: [register],
});

export const cm_docs_cache_misses = new client.Counter({
  name: 'cm_docs_cache_misses_total',
  help: 'Documentation cache misses',
  labelNames: ['type'],
  registers: [register],
});

export const cm_docs_operations = new client.Counter({
  name: 'cm_docs_operations_total',
  help: 'Documentation file operations',
  labelNames: ['operation'], // 'read', 'write', 'create', 'delete', 'rename'
  registers: [register],
});

// --- External Service Health ---

export const externalServiceUp = new client.Gauge({
  name: 'cm_external_service_up',
  help: 'Whether an external service is reachable (1=up, 0=down)',
  labelNames: ['service'],
  registers: [register],
});

// --- Helper Functions ---

export function recordEmailSent(campaignId: string) {
  emailsSentTotal.inc({ campaign_id: campaignId });
}

export function recordEmailFailed(campaignId: string, errorType: string = 'unknown') {
  emailsFailedTotal.inc({ campaign_id: campaignId, error_type: errorType });
}

export function setEmailQueueSize(size: number) {
  emailQueueSize.set(size);
}

export function recordLoginAttempt(status: 'success' | 'failure') {
  loginAttemptsTotal.inc({ status });
}

export function setActiveSessions(count: number) {
  activeSessions.set(count);
}

export function recordCampaignEmail(campaignId: string) {
  campaignEmailsTotal.inc({ campaign_id: campaignId });
}

export function recordResponseSubmission() {
  responseSubmissionsTotal.inc();
}

export function recordCanvassVisit(outcome: string) {
  canvassVisitsTotal.inc({ outcome });
}

export function setActiveCanvassSessions(count: number) {
  activeCanvassSessions.set(count);
}

export function recordShiftSignup() {
  shiftSignupsTotal.inc();
}

export function recordLocationQuery(endpoint: string, hasBounds: boolean, resultCount: number, durationSeconds: number) {
  locationQueryCount.inc({ endpoint, has_bounds: hasBounds.toString() });
  locationQueryDuration.observe({ endpoint, has_bounds: hasBounds.toString() }, durationSeconds);
  locationResultCount.observe({ endpoint }, resultCount);
}

export function setServiceUp(service: string, up: boolean) {
  externalServiceUp.set({ service }, up ? 1 : 0);
}

export function recordEmailTemplateUpdate(templateKey: string, userRole: string) {
  emailTemplatesUpdated.inc({ template_key: templateKey, user_role: userRole });
}

export function recordEmailTest(templateKey: string, success: boolean) {
  emailTestSent.inc({ template_key: templateKey, success: success.toString() });
}

export function recordTemplateRollback(templateKey: string) {
  emailTemplateRollback.inc({ template_key: templateKey });
}

export function recordTemplateCacheHit(templateKey: string) {
  emailTemplateCacheHit.inc({ template_key: templateKey });
}

export function recordTemplateCacheMiss(templateKey: string) {
  emailTemplateCacheMiss.inc({ template_key: templateKey });
}

export { register };
