{
  config,
  lib,
  pkgs,
  ...
}:
with lib; let
  serviceInterface = import ../../lib/service-interface.nix {inherit lib;};

  cfg = config.homelab.services.grafana;
  homelabCfg = config.homelab;

  # Default community dashboards with proper configuration
  defaultDashboards = {
    "node-exporter-full" = {
      name = "Node Exporter Full";
      id = 12486;
      revision = 2;
      # url = "https://grafana.com/api/dashboards/1860/revisions/37/download";
      sha256 = "sha256-1DE1aaanRHHeCOMWDGdOS1wBXxOF84UXAjJzT5Ek6mM=";

      url = "https://grafana.com/api/dashboards/12486/revisions/2/download";
    };
    "prometheus-2-0-stats" = {
      name = "Prometheus 2.0 Stats";
      id = 2;
      revision = 2;
      url = "https://grafana.com/api/dashboards/2/revisions/2/download";
      sha256 = "sha256-Ydk4LPwfX4qJN8tiWPLWQdtAqzj8CKi6HYsuE+kWcXw=";
    };
  };

  # Function to fetch a dashboard from Grafana.com
  fetchGrafanaDashboard = name: config:
    pkgs.fetchurl {
      inherit (config) url sha256;
      name = "${name}-dashboard.json";
    };

  # Git repository management for custom dashboards
  gitDashboardsRepo = mkIf (cfg.dashboards.git.enable && cfg.dashboards.git.url != "") (
    pkgs.fetchgit {
      url = cfg.dashboards.git.url;
      rev = cfg.dashboards.git.rev;
      sha256 = cfg.dashboards.git.sha256;
    }
  );

  # Dashboard provisioning configuration
  provisionDashboard = name: source: {
    "grafana-dashboards/${name}.json" = {
      inherit source;
      user = "grafana";
      group = "grafana";
      mode = "0644";
    };
  };

  # Generate dashboard files from various sources
  dashboardFiles =
    # Default community dashboards
    (foldl' (
      acc: name:
        acc // (provisionDashboard name (fetchGrafanaDashboard name defaultDashboards.${name}))
    ) {} (attrNames (filterAttrs (n: v: cfg.dashboards.defaults.${n}.enable) cfg.dashboards.defaults)))
    # Custom file-based dashboards
    // (foldl' (
        acc: dashboard:
          acc // (provisionDashboard dashboard.name dashboard.source)
      ) {}
      cfg.dashboards.files)
    # Git-synced dashboards
    // (optionalAttrs (cfg.dashboards.git.enable && cfg.dashboards.git.url != "") (
      let
        gitDashboards =
          if pathExists "${gitDashboardsRepo}/${cfg.dashboards.git.path}"
          then builtins.readDir "${gitDashboardsRepo}/${cfg.dashboards.git.path}"
          else {};
      in
        mapAttrs' (
          filename: type: let
            name = removeSuffix ".json" filename;
            source = "${gitDashboardsRepo}/${cfg.dashboards.git.path}/${filename}";
          in
            nameValuePair "grafana-dashboards/${name}.json" {
              inherit source;
              user = "grafana";
              group = "grafana";
              mode = "0644";
            }
        ) (filterAttrs (name: type: type == "regular" && hasSuffix ".json" name) gitDashboards)
    ));

  # Service-specific options beyond the standard interface
  grafanaServiceOptions = {
    # Authentication settings
    auth = {
      admin = {
        user = mkOption {
          type = types.str;
          default = "admin";
          description = "Admin username";
        };

        passwordFile = mkOption {
          type = types.nullOr types.path;
          default = null;
          description = "Path to admin password file";
        };

        email = mkOption {
          type = types.str;
          default = "admin@${homelabCfg.externalDomain}";
          description = "Admin email address";
        };
      };

      disableLoginForm = mkOption {
        type = types.bool;
        default = false;
        description = "Disable the login form";
      };

      oauthAutoLogin = mkOption {
        type = types.bool;
        default = false;
        description = "Enable OAuth auto-login";
      };

      anonymousAccess = {
        enable = mkOption {
          type = types.bool;
          default = false;
          description = "Enable anonymous access";
        };

        orgName = mkOption {
          type = types.str;
          default = "Homelab";
          description = "Organization name for anonymous users";
        };

        orgRole = mkOption {
          type = types.enum ["Viewer" "Editor" "Admin"];
          default = "Viewer";
          description = "Role for anonymous users";
        };
      };

      genericOauth = {
        enabled = mkOption {
          type = types.bool;
          default = false;
          description = "Enable generic OAuth";
        };

        configFile = mkOption {
          type = types.nullOr types.path;
          default = null;
          description = "Path to OAuth configuration file";
        };
      };
    };

    # Enhanced datasource configuration
    datasources = {
      prometheus = {
        enable = mkOption {
          type = types.bool;
          default = true;
          description = "Enable Prometheus datasource";
        };

        url = mkOption {
          type = types.str;
          default = "http://127.0.0.1:9090";
          description = "Prometheus URL";
        };

        uid = mkOption {
          type = types.str;
          default = "prometheus";
          description = "Unique identifier for Prometheus datasource";
        };

        scrapeInterval = mkOption {
          type = types.str;
          default = "15s";
          description = "Default scrape interval for Prometheus";
        };

        manageAlerts = mkOption {
          type = types.bool;
          default = true;
          description = "Manage alerts in Grafana";
        };

        exemplarTraceIdDestinations = mkOption {
          type = types.listOf types.attrs;
          default = [];
          description = "Exemplar trace ID destinations";
        };
      };

      loki = {
        enable = mkOption {
          type = types.bool;
          default = false;
          description = "Enable Loki datasource";
        };

        url = mkOption {
          type = types.str;
          default = "http://127.0.0.1:3100";
          description = "Loki URL";
        };

        uid = mkOption {
          type = types.str;
          default = "loki";
          description = "Unique identifier for Loki datasource";
        };

        maxLines = mkOption {
          type = types.int;
          default = 1000;
          description = "Maximum lines to return from Loki";
        };

        derivedFields = mkOption {
          type = types.listOf types.attrs;
          default = [];
          description = "Derived fields configuration for Loki";
        };
      };

      influxdb = {
        enable = mkOption {
          type = types.bool;
          default = false;
          description = "Enable InfluxDB datasource";
        };

        url = mkOption {
          type = types.str;
          default = "http://127.0.0.1:8086";
          description = "InfluxDB URL";
        };

        database = mkOption {
          type = types.str;
          default = "homelab";
          description = "InfluxDB database name";
        };

        tokenFile = mkOption {
          type = types.nullOr types.path;
          default = null;
          description = "Path to InfluxDB token file";
        };

        uid = mkOption {
          type = types.str;
          default = "influxdb";
          description = "Unique identifier for InfluxDB datasource";
        };

        version = mkOption {
          type = types.enum ["1.x" "2.x"];
          default = "2.x";
          description = "InfluxDB version";
        };

        organization = mkOption {
          type = types.str;
          default = "homelab";
          description = "InfluxDB organization (for v2.x)";
        };

        bucket = mkOption {
          type = types.str;
          default = "homelab";
          description = "InfluxDB bucket (for v2.x)";
        };
      };

      extra = mkOption {
        type = types.listOf types.attrs;
        default = [];
        description = "Additional data sources";
      };
    };

    # Enhanced dashboard configuration
    dashboards = {
      # Default community dashboards
      defaults = mkOption {
        type = types.attrsOf (types.submodule {
          options = {
            enable = mkOption {
              type = types.bool;
              default = false;
              description = "Enable this default dashboard";
            };
          };
        });
        default = mapAttrs (name: config: {enable = false;}) defaultDashboards;
        description = "Enable default community dashboards";
        example = literalExpression ''
          {
            "node-exporter-full".enable = true;
            "prometheus-2-0-stats".enable = true;
          }
        '';
      };

      # File-based dashboards
      files = mkOption {
        type = types.listOf (types.submodule {
          options = {
            name = mkOption {
              type = types.str;
              description = "Dashboard name (without .json extension)";
            };
            source = mkOption {
              type = types.path;
              description = "Path to dashboard JSON file";
            };
          };
        });
        default = [];
        description = "Dashboard files to provision";
      };

      # Git-based dashboard sync
      git = {
        enable = mkOption {
          type = types.bool;
          default = false;
          description = "Enable git-based dashboard synchronization";
        };

        url = mkOption {
          type = types.str;
          default = "";
          description = "Git repository URL for dashboards";
        };

        rev = mkOption {
          type = types.str;
          default = "HEAD";
          description = "Git revision to use";
        };

        sha256 = mkOption {
          type = types.str;
          default = "";
          description = "SHA256 hash of the git repository content";
        };

        path = mkOption {
          type = types.str;
          default = ".";
          description = "Path within the git repository containing dashboards";
        };

        updateInterval = mkOption {
          type = types.str;
          default = "1h";
          description = "How often to check for dashboard updates";
        };
      };

      path = mkOption {
        type = types.str;
        default = "/etc/grafana-dashboards";
        description = "Path where dashboard files are stored";
      };
    };

    # Plugin configuration
    plugins = mkOption {
      type = types.listOf types.package;
      default = [];
      description = "Grafana plugins to install";
    };

    # SMTP configuration
    smtp = {
      enable = mkOption {
        type = types.bool;
        default = false;
        description = "Enable SMTP for email notifications";
      };

      host = mkOption {
        type = types.str;
        default = "localhost:587";
        description = "SMTP server host:port";
      };

      user = mkOption {
        type = types.str;
        default = "";
        description = "SMTP username";
      };

      passwordFile = mkOption {
        type = types.nullOr types.path;
        default = null;
        description = "Path to SMTP password file";
      };

      fromAddress = mkOption {
        type = types.str;
        default = "grafana@${homelabCfg.externalDomain}";
        description = "From email address";
      };

      fromName = mkOption {
        type = types.str;
        default = "Homelab Grafana";
        description = "From name";
      };

      skipVerify = mkOption {
        type = types.bool;
        default = false;
        description = "Skip SSL certificate verification";
      };
    };

    # Security settings
    security = {
      secretKeyFile = mkOption {
        type = types.nullOr types.path;
        default = null;
        description = "Path to secret key file for signing";
      };

      allowEmbedding = mkOption {
        type = types.bool;
        default = false;
        description = "Allow embedding Grafana in iframes";
      };

      cookieSecure = mkOption {
        type = types.bool;
        default = true;
        description = "Set secure flag on cookies";
      };

      contentSecurityPolicy = mkOption {
        type = types.bool;
        default = true;
        description = "Enable Content Security Policy header";
      };

      strictTransportSecurity = mkOption {
        type = types.bool;
        default = true;
        description = "Enable Strict Transport Security header";
      };
    };

    # Data directory
    dataDir = mkOption {
      type = types.str;
      default = "/var/lib/grafana";
      description = "Directory to store Grafana data";
    };

    # Extra Grafana settings
    extraSettings = mkOption {
      type = types.attrs;
      default = {};
      description = "Additional Grafana settings";
    };
  };

  # Enhanced datasource configuration
  buildDatasources = let
    # Build prometheus datasource
    prometheusDatasource = optional cfg.datasources.prometheus.enable {
      uid = cfg.datasources.prometheus.uid;
      name = "Prometheus";
      type = "prometheus";
      url = cfg.datasources.prometheus.url;
      access = "proxy";
      isDefault = true;
      editable = false;
      jsonData = {
        timeInterval = cfg.datasources.prometheus.scrapeInterval;
        queryTimeout = "60s";
        httpMethod = "POST";
        manageAlerts = cfg.datasources.prometheus.manageAlerts;
        exemplarTraceIdDestinations = cfg.datasources.prometheus.exemplarTraceIdDestinations;
      };
    };

    # Build loki datasource
    lokiDatasource = optional cfg.datasources.loki.enable {
      uid = cfg.datasources.loki.uid;
      name = "Loki";
      type = "loki";
      url = cfg.datasources.loki.url;
      access = "proxy";
      editable = false;
      jsonData = {
        maxLines = cfg.datasources.loki.maxLines;
        derivedFields = cfg.datasources.loki.derivedFields;
      };
    };

    # Build influxdb datasource
    influxdbDatasource = optional cfg.datasources.influxdb.enable {
      uid = cfg.datasources.influxdb.uid;
      name = "InfluxDB";
      type = "influxdb";
      url = cfg.datasources.influxdb.url;
      access = "proxy";
      database = cfg.datasources.influxdb.database;
      editable = false;
      jsonData = {
        dbName = cfg.datasources.influxdb.database;
        httpHeaderName1 = "Authorization";
        version = cfg.datasources.influxdb.version;
        organization = cfg.datasources.influxdb.organization;
        defaultBucket = cfg.datasources.influxdb.bucket;
      };
      secureJsonData = mkIf (cfg.datasources.influxdb.tokenFile != null) {
        httpHeaderValue1 = "$__file{${cfg.datasources.influxdb.tokenFile}}";
      };
    };

    # Build extra datasources
    extraDatasources = cfg.datasources.extra;
  in
    prometheusDatasource ++ lokiDatasource ++ influxdbDatasource ++ extraDatasources;
in {
  options.homelab.services.grafana = serviceInterface.mkServiceInterface {
    serviceName = "grafana";
    defaultPort = 3000;
    defaultSubdomain = "grafana";
    monitoringPath = "/metrics";
    healthCheckPath = "/api/health";
    healthCheckConditions = [
      "[STATUS] == 200"
      "[BODY].database == ok"
      "[RESPONSE_TIME] < 2000"
    ];
    serviceOptions = grafanaServiceOptions;
  };

  config = serviceInterface.mkServiceConfig {
    inherit config cfg homelabCfg;
    serviceName = "grafana";

    extraMonitoringLabels = {
      component = "dashboard";
    };

    # Additional health checks specific to Grafana
    customHealthChecks = [];

    serviceConfig = mkMerge [
      {
        services.grafana = {
          enable = true;
          dataDir = cfg.dataDir;
          # declarativePlugins =
          #   cfg.plugins
          #   ++ (with pkgs.grafanaPlugins; [
          #     grafana-exploretraces-app
          #     grafana-metricsdrilldown-app
          #     grafana-pyroscope-app
          #     grafana-lokiexplore-app
          #     grafana-worldmap-panel
          #     grafana-piechart-panel
          #   ]);

          settings =
            recursiveUpdate {
              server = {
                http_port = cfg.port;
                http_addr = "0.0.0.0";
                domain = "${cfg.proxy.subdomain}.${homelabCfg.externalDomain}";
                root_url = "https://${cfg.proxy.subdomain}.${homelabCfg.externalDomain}";
                serve_from_sub_path = false;
              };

              database = {
                type = "sqlite3";
                path = "${cfg.dataDir}/grafana.db";
              };

              security =
                {
                  admin_user = cfg.auth.admin.user;
                  admin_email = cfg.auth.admin.email;
                  # allow_embedding = cfg.security.allowEmbedding;
                  # cookie_secure = cfg.security.cookieSecure;
                  # content_security_policy = cfg.security.contentSecurityPolicy;
                  # strict_transport_security = cfg.security.strictTransportSecurity;
                }
                // (optionalAttrs (cfg.auth.admin.passwordFile != null) {
                  admin_password = "$__file{${cfg.auth.admin.passwordFile}}";
                })
                // (optionalAttrs (cfg.security.secretKeyFile != null) {
                  secret_key = "$__file{${cfg.security.secretKeyFile}}";
                });

              users = {
                allow_sign_up = false;
                auto_assign_org = true;
                auto_assign_org_role = "Viewer";
              };

              "auth.anonymous" = {
                enabled = cfg.auth.anonymousAccess.enable;
                org_name = cfg.auth.anonymousAccess.orgName;
                org_role = cfg.auth.anonymousAccess.orgRole;
              };

              "auth.basic" = {
                enabled = !cfg.auth.disableLoginForm;
              };

              "auth.generic_oauth" =
                mkIf cfg.auth.genericOauth.enabled {
                  enabled = true;
                }
                // (optionalAttrs (cfg.auth.genericOauth.configFile != null) {
                  client_id = "$__file{${cfg.auth.genericOauth.configFile}}";
                });

              smtp = mkIf cfg.smtp.enable ({
                  enabled = true;
                  host = cfg.smtp.host;
                  user = cfg.smtp.user;
                  from_address = cfg.smtp.fromAddress;
                  from_name = cfg.smtp.fromName;
                  skip_verify = cfg.smtp.skipVerify;
                }
                // (optionalAttrs (cfg.smtp.passwordFile != null) {
                  password = "$__file{${cfg.smtp.passwordFile}}";
                }));

              analytics = {
                reporting_enabled = false;
                check_for_updates = false;
              };
              news.news_feed_enabled = false;

              feature_toggles = {
                provisioning = true;
                kubernetesDashboards = true;
              };
              # paths = {
              #   plugins = "${cfg.dataDir}/plugins";
              #   provisioning = "/etc/grafana/provisioning";
              # };
            }
            cfg.extraSettings;

          provision = {
            enable = true;

            datasources.settings.datasources = buildDatasources;

            dashboards.settings.providers = [
              {
                name = "homelab-dashboards";
                type = "file";
                disableDeletion = false;
                updateIntervalSeconds = 10;
                allowUiUpdates = true;
                options = {
                  path = cfg.dashboards.path;
                };
              }
            ];
          };
        };

        # Provision dashboard files
        environment.etc = dashboardFiles;

        # Ensure dashboard directory exists
        systemd.tmpfiles.rules = [
          "d ${cfg.dashboards.path} 0755 grafana grafana -"
        ];
      }

      # Git dashboard sync service (if enabled)
      (mkIf (cfg.dashboards.git.enable && cfg.dashboards.git.url != "") {
        systemd.services.grafana-dashboard-sync = {
          description = "Sync Grafana dashboards from git";
          after = ["grafana.service"];
          wantedBy = ["multi-user.target"];

          serviceConfig = {
            Type = "oneshot";
            User = "grafana";
            Group = "grafana";
          };

          script = ''
            echo "Syncing dashboards from git repository..."
            # Dashboard files are already provisioned via Nix
            # This service can be extended for runtime updates if needed
            systemctl reload grafana.service
          '';
        };

        systemd.timers.grafana-dashboard-sync = {
          description = "Timer for Grafana dashboard sync";
          wantedBy = ["timers.target"];

          timerConfig = {
            OnCalendar = cfg.dashboards.git.updateInterval;
            Persistent = true;
          };
        };
      })
    ];
  };
}
