#pragma once

#include <Arduino.h>
#include <SD.h>
#include <SPI.h>
#include <XPowersLib.h>

class MicrophoneRecorder {
 public:
  struct MicRuntimeConfig {
    int dataPin;
    int clkPin;
    int selectPin;
    bool selectLeft;
  };

  explicit MicrophoneRecorder(Print& out = Serial);
  ~MicrophoneRecorder();

  bool begin();
  void setRuntimeConfig(const MicRuntimeConfig& cfg);
  const MicRuntimeConfig& runtimeConfig() const { return micCfg_; }
  bool activateMicrophone();
  void deactivateMicrophone();

  bool open(const char* path);
  bool openTimestamped();
  bool captureForMs(uint32_t durationMs);
  void close();

  bool isSdReady() const { return sdReady_; }
  bool isMicActive() const { return micActive_; }
  bool isOpen() const { return fileOpen_; }
  const char* currentPath() const { return currentPath_; }

 private:
  struct WavHeader {
    char riff[4];
    uint32_t chunkSize;
    char wave[4];
    char fmt[4];
    uint32_t subchunk1Size;
    uint16_t audioFormat;
    uint16_t numChannels;
    uint32_t sampleRate;
    uint32_t byteRate;
    uint16_t blockAlign;
    uint16_t bitsPerSample;
    char data[4];
    uint32_t dataSize;
  };

  void logf(const char* fmt, ...);
  bool initPmu();
  void forceSpiDeselected();
  void cycleSdRail(uint32_t offMs = 250, uint32_t onSettleMs = 700);
  bool mountSdCard();
  bool tryMountWithBus(SPIClass& bus, const char* busName, uint32_t hz);
  bool ensureDirectory(const char* path);
  bool writeWavHeader();
  bool finalizeWavHeader();
  uint32_t selectTimestamp() const;

  Print& out_;
  SPIClass sdSpiH_{HSPI};
  SPIClass sdSpiF_{FSPI};
  SPIClass* activeSdSpi_ = nullptr;
  XPowersLibInterface* pmu_ = nullptr;
  File file_;
  char currentPath_[96] = {0};
  uint32_t logSeq_ = 0;
  uint32_t wavDataBytes_ = 0;
  bool pmuReady_ = false;
  bool sdReady_ = false;
  bool micActive_ = false;
  bool fileOpen_ = false;
  MicRuntimeConfig micCfg_{};
};
